Consider a hypothetical method of an object that does stuff for you:
public class DoesStuff
{
BackgroundWorker _worker = new BackgroundWorker();
...
public void CancelDoingStuff()
{
_worker.CancelAsync();
//todo: Figure out a way to wait for it to be cancelled
}
}
How can one wait for a BackgroundWorker to be done? In the past people have tried:
while (!_worker.IsDone)
{
Sleep(100);
}
But this is a deadlock, since the IsBusy is not cleared until after the RunWorkerCompleted event is handled, and that event won't get handled until the application goes idle. (Plus, it's a busy loop - and how disgusting is that)
Others have add suggested kludging it into:
while (!_worker.IsDone)
{
Application.DoEvents();
}
Problem with that is that is Application.DoEvents()
causes messages currently in the queue to be processed, which cause reentrantcy problems.
i would hope to use some solution involving Event synchronization objects, where the code waits for an event that the worker's RunWorkerCompleted event handlers sets, something like:
Event _workerDoneEvent = new WaitHandle();
public void CancelDoingStuff()
{
_worker.CancelAsync();
_workerDoneEvent.WaitOne();
}
private void RunWorkerCompletedEventHandler(sender object, RunWorkerCompletedEventArgs e)
{
_workerDoneEvent.SetEvent();
}
But i'm back to the deadlock: the event handler can't run until the application goes idle, and the application won't go idle because it's waiting for an Event.
So how can you wait for an BackgroundWorker to finish?
Update People seem to be confused by this question. They seem to think that i will be using the BackgroundWorker as:
BackgroundWorker worker = new BackgroundWorker();
worker.DoWork += MyWork;
worker.RunWorkerAsync();
WaitForWorkerToFinish(worker);
That is not it, that is not what i'm doing, and that is not what is being asked here. If that were the case, there would be no point in using a background worker.