考虑一个为您做事的对象的假设方法:
public class DoesStuff
{
BackgroundWorker _worker = new BackgroundWorker();
...
public void CancelDoingStuff()
{
_worker.CancelAsync();
//todo: Figure out a way to wait for BackgroundWorker to be cancelled.
}
}
如何等待 BackgroundWorker 完成?
过去人们曾尝试过:
while (_worker.IsBusy)
{
Sleep(100);
}
但是这个死锁,因为IsBusy
直到RunWorkerCompleted
事件被处理之后才会被清除,并且在应用程序空闲之前无法处理该事件。在工作人员完成之前,应用程序不会空闲。(另外,这是一个繁忙的循环 - 恶心。)
其他人建议将其添加到:
while (_worker.IsBusy)
{
Application.DoEvents();
}
这样做的问题是Application.DoEvents()
导致当前在队列中的消息被处理,这会导致重入问题(.NET 不能重入)。
我希望使用一些涉及事件同步对象的解决方案,其中代码等待事件 - 工作人员的RunWorkerCompleted
事件处理程序设置。就像是:
Event _workerDoneEvent = new WaitHandle();
public void CancelDoingStuff()
{
_worker.CancelAsync();
_workerDoneEvent.WaitOne();
}
private void RunWorkerCompletedEventHandler(sender object, RunWorkerCompletedEventArgs e)
{
_workerDoneEvent.SetEvent();
}
但是我又回到了死锁:事件处理程序在应用程序空闲之前无法运行,并且应用程序不会因为正在等待事件而空闲。
那么你怎么能等待 BackgroundWorker 完成呢?
更新 人们似乎对这个问题感到困惑。他们似乎认为我会将 BackgroundWorker 用作:
BackgroundWorker worker = new BackgroundWorker();
worker.DoWork += MyWork;
worker.RunWorkerAsync();
WaitForWorkerToFinish(worker);
不是这样,这不是我正在做的,也不是这里要问的。如果是这样的话,使用后台工作人员就没有意义了。