在有关方法的MSDN 文章BackgroundWorker.CancelAsync
中,有一条警告说:
请注意,
DoWork
事件处理程序中的代码可能会在发出取消请求时完成其工作,并且您的轮询循环可能会错过CancellationPending
设置为true。在这种情况下,即使发出了取消请求,事件处理程序中 的Cancelled
标志 也不会设置为true 。这种情况称为 竞争条件,是多线程编程中常见的问题。System.ComponentModel.RunWorkerCompletedEventArgs
RunWorkerCompleted
避免这种竞争条件的正确和好的解决方案是什么?
这是我的示例代码,它引发了这种情况的出现:
public partial class MainWindow : Window
{
BackgroundWorker bW;
int bWsCount = 0;
public MainWindow()
{
InitializeComponent();
}
private void Window_MouseMove(object sender, MouseEventArgs e)
{
if (bW != null)
bW.CancelAsync();
bW = new BackgroundWorker();
bW.WorkerSupportsCancellation = true;
bW.DoWork += new DoWorkEventHandler(bW_DoWork);
bW.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bW_RunWorkerCompleted);
bW.RunWorkerAsync(0);
bWsCount++;
labelBackgroundWorkersCount.Content = bWsCount;
}
void bW_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
BackgroundWorker worker = sender as BackgroundWorker;
if (e.Cancelled || worker.CancellationPending)
{
bWsCount--;
labelBackgroundWorkersCount.Content = bWsCount;
}
else
worker.RunWorkerAsync(1000);
}
void bW_DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker worker = sender as BackgroundWorker;
int sleepDuration = Convert.ToInt32(e.Argument);
if (worker.CancellationPending) { e.Cancel = true; return; }
Thread.Sleep(sleepDuration);
if (worker.CancellationPending) { e.Cancel = true; return; }
}
}