How to wait correctly until BackgroundWorker completes?
Solution 1:
Try using the AutoResetEvent class like this:
var doneEvent = new AutoResetEvent(false);
var bw = new BackgroundWorker();
bw.DoWork += (sender, e) =>
{
try
{
if (!e.Cancel)
{
// Do work
}
}
finally
{
doneEvent.Set();
}
};
bw.RunWorkerAsync();
doneEvent.WaitOne();
Caution: You should make sure that doneEvent.Set()
is called no matter what happens. Also you might want to provide the doneEvent.WaitOne()
with an argument specifying a timeout period.
Note: This code is pretty much a copy of Fredrik Kalseth answer to a similar question.
Solution 2:
To wait for a background worker thread (single or multiple) do the following:
-
Create a List of Background workers you have programatically created:
private IList<BackgroundWorker> m_WorkersWithData = new List<BackgroundWorker>();
-
Add the background worker in the list:
BackgroundWorker worker = new BackgroundWorker(); worker.DoWork += new DoWorkEventHandler(worker_DoWork); worker.ProgressChanged += new ProgressChangedEventHandler(worker_ProgressChanged); worker.WorkerReportsProgress = true; m_WorkersWithData.Add(worker); worker.RunWorkerAsync();
-
Use the following function to wait for all workers in the List:
private void CheckAllThreadsHaveFinishedWorking() { bool hasAllThreadsFinished = false; while (!hasAllThreadsFinished) { hasAllThreadsFinished = (from worker in m_WorkersWithData where worker.IsBusy select worker).ToList().Count == 0; Application.DoEvents(); //This call is very important if you want to have a progress bar and want to update it //from the Progress event of the background worker. Thread.Sleep(1000); //This call waits if the loop continues making sure that the CPU time gets freed before //re-checking. } m_WorkersWithData.Clear(); //After the loop exits clear the list of all background workers to release memory. //On the contrary you can also dispose your background workers. }