BackgroundWorker - Cancellation Pending 在 RunWorkerCompleted 中更改为 false。为什么?

2024-04-01

取消BackGroundWorker后,在DoWork中,CancellationPending为true,但是当他来到RunWorkerCompleted时,CancellationPending为false。我不知道我做错了什么?

static BackgroundWorker b1;

static void Main(string[] args)
{
    b1=new BackgroundWorker();
    b1.DoWork += new DoWorkEventHandler(work1);
    b1.RunWorkerCompleted += new RunWorkerCompletedEventHandler(completed);
    b1.WorkerSupportsCancellation = true;
    b1.RunWorkerAsync("Hellow");
    Console.ReadLine();
}

private static void completed(object sender, RunWorkerCompletedEventArgs e)
{
    if (((BackgroundWorker)sender).CancellationPending)
        Console.WriteLine("Canceled!");
    else
        Console.WriteLine("Result:" + e.Result);//it goes here every time
}

private static void work1(object sender, DoWorkEventArgs e)
{
    ((BackgroundWorker)sender).CancelAsync();
    if (((BackgroundWorker)sender).CancellationPending)
    {
        e.Cancel = true;
    }
}

顺便说一句,如何将 DoWork 中发生的错误添加到 RunWorkerCompletedEventArgs.Error 中以将其显示给用户?


是的,BackgroundWorker 类在引发 RunWorkerCompleted 事件之前将 CancellationPending 属性设置为 false。工人是否真的被取消了。

这是有意为之的,它可以防止您陷入使用线程时始终存在的令人讨厌的陷阱。由于一种称为“线程竞争”的错误,使用线程的代码通常会随机且不可预测地出现错误行为。这是一种非常常见的错误,并且非常难以调试。

如果 BGW 没有这样做,您的预期方法中很容易出错的是,当您看到 CancellationPending 设置为 true 时,您会认为工作线程已被取消。但这是一种错觉,你无法区分它被取消和正常完成之间的区别。极端情况是您在工作线程完成前一微秒调用 CancelAsync() 。工作线程甚至没有机会看到 CancellationPending 标志设置为 true,它正忙着完成 DoWork 事件处理程序方法的最后几位。这是一场线程竞赛,工作人员在您的调用之前竞赛并正常完成。

避免此错误的正确握手方法是,当工作线程看到 CancellationPending 属性设置为 true 时,将 e.Cancel 设置为 true。当然还要停止它正在做的事情。现在可靠了,RunWorkerCompleted 事件处理程序中的 e.Cancelled 属性是 e.Cancel 的副本。因此,您的代码现在可以可靠地告诉您工作人员是否看到了取消请求。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

BackgroundWorker - Cancellation Pending 在 RunWorkerCompleted 中更改为 false。为什么? 的相关文章

随机推荐