How to wait correctly until BackgroundWorker completes?
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.
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.}
BackgroundWorker has a completion event. Instead of waiting, call your remaining code path from the completion handler.