考虑一个为您 做事 的对象的 假设 方法:
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事件被处理后才被清除,并且该事件只有在应用程序变得空闲之后才能得到处理。直到工作人员完成后,应用程序才会处于空闲状态。(此外,这是一个繁忙的循环- 令人作呕。)
IsBusy
RunWorkerCompleted
其他人则建议将其合并为:
while (_worker.IsBusy) { Application.DoEvents(); }
这样做的问题是Application.DoEvents()导致当前队列中的消息被处理,从而导致重新输入问题(.NET不能重新输入)。
Application.DoEvents()
我希望使用一些涉及事件同步对象的解决方案,其中代码 等待 事件-工作者的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);
这是 不是 它,那是 不是 我在做什么,那就是 没有 什么被要求在这里。如果真是这样,那么使用后台工作人员将毫无意义。
如果我了解您的要求正确,则可以执行以下操作(代码未经测试,但显示了总体思路):
private BackgroundWorker worker = new BackgroundWorker(); private AutoResetEvent _resetEvent = new AutoResetEvent(false); public Form1() { InitializeComponent(); worker.DoWork += worker_DoWork; } public void Cancel() { worker.CancelAsync(); _resetEvent.WaitOne(); // will block until _resetEvent.Set() call made } void worker_DoWork(object sender, DoWorkEventArgs e) { while(!e.Cancel) { // do something } _resetEvent.Set(); // signal that worker is done }