I don't think that the scenario is really that one BackgroundWorker
should wait for another. What you really want is to fire some UI event after (and only after) both of them complete. It's a subtle but important difference; the second version is a lot easier to code.
public class Form1 : Form
{
private object download1Result;
private object download2Result;
private void BeginDownload()
{
// Next two lines are only necessary if this is called multiple times
download1Result = null;
download2Result = null;
bwDownload1.RunWorkerAsync();
bwDownload2.RunWorkerAsync();
}
private void bwDownload1_RunWorkerCompleted(object sender,
RunWorkerCompletedEventArgs e)
{
download1Result = e.Result;
if (download2Result != null)
DisplayResults();
}
private void bwDownload2_RunWorkerCompleted(object sender,
RunWorkerCompletedEventArgs e)
{
download2Result = e.Result;
if (download1Result != null)
DisplayResults();
}
private void DisplayResults()
{
// Do something with download1Result and download2Result
}
}
Note that those object
references should be strongly-typed, I just used object
because I don't know what you're downloading.
This is really all you need; the RunWorkerCompleted
event runs in the foreground thread so you actually don't need to worry about synchronization or race conditions in there. No need for lock
statements, AutoResetEvent
, etc. Just use two member variables to hold the results, or two boolean flags if the result of either can actually be null
.