关闭应用程序时BackgroundWorker线程的关闭程度

本文关键字:程度 线程 应用程序 BackgroundWorker | 更新日期: 2023-09-27 18:10:16

我用BackgroundWorker创建线程,并在循环中每次检查CancellationPending是否为真,如下所示:

   public MainPage()
    {
        InitializeComponent();
        bw = new BackgroundWorker();
        bw.WorkerReportsProgress = true;
        bw.WorkerSupportsCancellation = true;
        bw.DoWork += new DoWorkEventHandler(bw_DoWork);
        bw.ProgressChanged += new ProgressChangedEventHandler(bw_ProgressChanged);
        bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted);
    }
    private void ButtonStart_Click(object sender, RoutedEventArgs e)
    {
        if (bw.IsBusy != true)
        {
            bw.RunWorkerAsync();
        }
    }
    private void ButtonCancel_Click(object sender, RoutedEventArgs e)
    {
        if (bw.WorkerSupportsCancellation)
        {
            bw.CancelAsync();
        }
    }
    private void bw_DoWork(object sender, DoWorkEventArgs e)
    {
        BackgroundWorker worker = sender as BackgroundWorker;
        for (int i = 1; i <= 100; i++)
        {
            Debug.WriteLine("The tread is working");
            if (worker.CancellationPending)
            {
                e.Cancel = true;
                bw.CancelAsync();
                break;
            }
            else
            {
                System.Threading.Thread.Sleep(500);
                worker.ReportProgress(i);
            }
        }
    }
    private void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        if (e.Cancelled)
        {
            tbProgress.Text = "Canceled";
        }
        else if (e.Error != null)
        {
            tbProgress.Text = "Error: " + e.Error.Message;
        }
        else
        {
            tbProgress.Text = "Done";
        } 
    }
    private void bw_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
        tbProgress.Text = e.ProgressPercentage.ToString() + "%";
    }

当应用程序被停用时,线程没有被关闭,它被中止并发生异常。如何关闭线程与BackgroundWorker时,应用程序停用?

关闭应用程序时BackgroundWorker线程的关闭程度

当一个应用程序被停用时,除了主UI线程之外的每个线程都会在它激活时抛出ThreadAbortException。这似乎是"设计"的一种方式,迫使应用程序迅速停止他们正在做的事情。线程可以捕获ThreadAbortException并结束它们正在做的事情,但要注意,ThreadAbortException将在catch块结束时再次自动引发。finally块中的任何代码也将被执行。

对于你的特定问题,当应用程序被停用时,没有理由试图取消BackgroundWorker,因为ThreadAbortException会发生,并将有效地停止后台worker。如果你想在发生这种情况时做一些事情来清理,你可以在bw_DoWork中捕获ThreadAbortException,做你需要做的事情,然后让它死亡。

要让它在激活后再次启动,你必须重新启动后台工作器,就像你第一次运行应用程序一样。

您是否将BackgroundWorker设置为可取消?

 var bg= new BackgroundWorker();
 bg.WorkerSupportsCancellation = true;

来自文档:

如果你想让BackgroundWorker支持取消,设置WorkerSupportsCancellation属性为true。当此属性为true时,您可以调用CancelAsync方法来中断后台操作。

你的代码似乎是错误的,你应该调用你的线程代码之外的CancelAsync(),这将设置CancellationPending标志,你可以用它来退出循环。

虽然我不是100%确定,因为我不知道bw变量是从哪里来的。'

你应该在你的工作方法中检查CancellationPending标志,如果这个标志被设置了,你应该优雅地退出。
取消工作的条件是什么?取消按钮点击?然后你应该把CancelAsync(…)调用放在那里。它将为您设置CancellationPending标志,您已经在您的代码中检查,避免需要ResetEvent对象之类的东西。

根据我自己的观察,我想对上面的答案补充一点澄清。当实例被保留时,后台线程在去激活/激活中存活

我的代码看起来像这样:

private void Application_Activated(object sender, ActivatedEventArgs e)
{
    if (e.IsApplicationInstancePreserved)
    {
        Log.write("Activating, instance preserved");
        // restart long-running network requests
        startBackground();
    }
    else // start over again
    {
        AppSettings.init();
        Log.write("Activating, rehydrating" );
        startBackground();
    }
}

我还记录了BackgroundWorker对象执行时的哈希码。我看到的是,每当我收到"正在激活,实例保留"消息时,我就会有一个额外的BackgroundWorker正在运行。

基于此,似乎更准确地说线程在墓碑上被终止,而不是在停用时?