首页 文章

停止并重新启动BGWorker时,取消标志是否会受到竞争条件的影响?

提问于
浏览
1

我见过这个answer

是的,BackgroundWorker类在引发RunWorkerCompleted事件之前将CancellationPending属性设置为false .

以及CancelAsyncRunWorkerAsync的文档

我有这个代码阻止 InvalidOperationException 被抛出 . 这是我的代码,所以 WorkerSupportsCancellation 是真的 .

public void Start()
{
    lock (OnOffLock)
    {
        if (worker.IsBusy)
            return;
        worker.RunWorkerAsync();
    }
}
public void Stop()
{
    lock (OnOffLock)
    {
        worker.CancelAsync();
    }
}

我知道如果我在工作人员已经停止(无论出于何种原因)时呼叫CancelAsync,就没有办法避免发生可能的竞争条件 . 我想知道的是它可能是常识,但在文档中没有解释 .

当调用 RunWorkerAsync (例如,在停止后重新启动工作程序)时, CancellationPending 设置为false以避免未处理的取消?

我的猜测是,当调用 RunWorkerAsync 时, CancellationPending 标志设置为false,无论它以前的值是什么,但我没有找到确认 .

2 回答

  • 1

    根据这是正确的:BackgroundWorker.cs

    public void RunWorkerAsync(object argument)
        {
            if (isRunning)
            {
                throw new InvalidOperationException(SR.GetString(SR.BackgroundWorker_WorkerAlreadyRunning));
            }
    
            isRunning = true;
            cancellationPending = false;
    
            asyncOperation = AsyncOperationManager.CreateOperation(null);
            threadStart.BeginInvoke(argument,
                                    null,
                                    null);
        }
    
  • 1

    是的,有很强的竞争潜力 . 您的RunWorkerCompleted事件处理程序可能需要一段时间才能开始运行,这取决于您的UI线程正在执行的操作 . 它可能需要很长时间才能完成,并且您无法从UI线程中找到它 . BGW重置CancellationPending的原因,它没有告诉你任何关于真实情况的信息 .

    您必须仔细编码,以便检测到它实际上已被取消 . 大致:

    private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) {
            (some-loop-construct) {
                if (backgroundWorker1.CancellationPending) {
                   e.Cancel = true;    // Important!
                   return;
                }
                // etc...
            }
        }
    
        private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) {
            if (e.Error != null) {
                // Something bad happened
            }
            else if (e.Cancelled) {
                // It actually got cancelled
            }
            else {
                // It actually completed
            }
        }
    

    在DoWork事件处理程序中将e.Cancel设置为true非常重要,这就是在RunWorkerCompleted事件处理程序中设置e.Cancelled的原因

相关问题