【问题标题】:wpf cancel backgroundworker on application exitswpf 在应用程序退出时取消后台工作程序
【发布时间】:2010-03-26 13:05:03
【问题描述】:

在我的应用程序中,我有一个主窗口,并在其中加载一个页面。当用户按下按钮时,此页面会执行很长时间的任务。我的问题是,当正在执行长任务并且用户按下主窗口的关闭按钮时,应用程序似乎没有完成,因为我正在 VS2008 中调试它,我可以看到突出显示的停止按钮。如果我想完成我必须按下停止按钮,应用程序不会在应用程序退出时自动停止调试。我认为 .NET 在应用程序退出时会自动停止后台工作程序,但在看到这种行为后我不确定。我试图在卸载的事件页面中强制和取消后台工作人员,如下所示:

    private void Page_Unloaded(object sender, RoutedEventArgs e)
    {
        // Is the Background Worker do some work?
        if (My_BgWorker != null && My_BgWorker.IsBusy)
        {
            //If it supports cancellation, Cancel It
            if (My_BgWorker.WorkerSupportsCancellation)
            {
                // Tell the Background Worker to stop working.
                My_BgWorker.CancelAsync();
            }
        }


    }

但没有成功。执行 CancelAsync() 后,几分钟后,我可以看到 backgroundworker 完成并引发 RunWorkerCompleted,我可以看到任务已完成检查事件中的 e.Cancelled 参数,但是在执行此事件后,应用程序继续而不退出,我有不知道在做什么......

我将 WorkerSupportsCancellation 设置为 true 以支持一开始的取消。

我会感谢所有答案。谢谢。

【问题讨论】:

    标签: wpf backgroundworker exit


    【解决方案1】:

    取消不是自动的,DoWork 事件处理程序中的代码需要通过检查 CancellationPending 属性的值来处理取消。调用CancelAsync 不会中止线程,它只是将CancellationPending 设置为true...

    例如:

    private void bgw_DoWork(object sender, DoWorkEventArgs e)
    {
        while(!bgw.CancellationPending)
        {
            ...
        }
    }
    

    【讨论】:

    • 好的,当我做 My_BgWorker.CancelAsync();从正在执行后台工作程序的页面中,它将 CancellationPending 设置为 true,现在我正在检查 DoWork 这个属性值。然后当它为 true 时,我完成了 DoWork 方法,但我不明白一件事:当 RunWorkerCompleted 事件引发时退出 DoWork ,作为 RunWorkerCompletedEventArgs 的参数 e 应该是 e.Cancelled=true 而不是 false 因为我已经完成了:My_BgWorker.CancelAsync() 还是我很困惑?如果我已请求使用 CancelAsync() 取消后台操作,为什么我收到 e.cancelled 为 false 而不是 true?
    • e.Cancel 应在 DoWork 事件中设置,如果已考虑取消请求
    • 是的,在 DoWork 事件中,我在其末尾放置了一个断点,并且 CancellationPending 设置为 true,但是当 DoWork 完成后引发 RunWorkerCompleted 事件时,RunWorkerCompleted 中的 e.Cancelled 属性为 false。正常吗?不应该是真的(因为我要求取消后台工作者操作)?
    • 这就是我告诉你的:如果你考虑了取消请求,你需要在 DoWork 中将 e.Cancel 设置为 true。 RunWorkerCompleted 中 e.Cancelled 的值将反映 DoWork 中 e.Cancel 的值
    • 好的!解决了!我被你误解了。对不起。现在它可以工作了;)我在 RunWorkerCompleted 中收到取消为假;)现在我唯一的问题是我对 Hanin 说的话。退出时应用程序似乎没有退出...退出应用程序时VS2008中的调试不会停止。
    【解决方案2】:

    我认为 Thomas Levesque 指出了这个问题。

    一般来说:某处,某个线程仍在执行。您可以通过暂停调试过程(暂停按钮,名为“Break All”)尝试找出线程是什么。此时,应突出显示下一个执行的代码行。此外,您可以使用“线程”窗口(在 Debug -> Windows 下)准确查看仍在运行的线程以及在何处运行。

    【讨论】:

    • 好的,我已经按照你说的做了,按下暂停键,但是没有一行被高亮并且在线程窗口中我只能看到一个进程 GParts.vshost.exe。按下关闭按钮应用程序后,我可以看到 DoWork 方法已完成,然后使用 e.Cancelled 参数引发的 RunWorkerCompleted 事件为 false(我不明白我对 Thomas 说的为什么它没有设置为 true,因为我执行了 cancelASync())并且应用程序似乎没有退出(没有调试停止)。在这种情况下,我暂停调试,没有突出显示任何行,然后我转到您所说的线程窗口,它出现一个进程。
    【解决方案3】:

    完美的 Thomas,如您所说,将 ShutdownMode 设置为 OnMainWindowClose 解决了我的问题。现在调试器正确停止了;)非常感谢您帮助我。

    我所做的是:

           <Application 
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"                        
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             x:Class="GParts.App"
             StartupUri="WinMain.xaml"
             ShutdownMode="OnMainWindowClose">
    
                       <...>
    
            </Application>
    

    最后,我想在 DoWork 事件中对 backgroundworker 做一件事,以防某种类型的错误引发异常:我使用 try catch 子句处理其中的错误并进入 catch 我做:

            catch (Exception ex)
            {
                e.Result = ex.Message;               
            }
    

    当后台工作人员因异常完成时,我希望在 RunWorkerCompleted 中使用 e.Error 检测它并显示它。所以我在 RunWorkerCompleted 中所做的是:

            if (e.Cancelled)
            {
                // Cancelled
    
            }
            else if (e.Error != null)
            {
                // Exception Thrown
                // Here I want to show the message that produced the exception in DoWork
                // event. If I set  e.Result = ex.Message in DoWork event, is e.Error here
                // containing ex.Message?
    
    
            }
            else
            {
                // Completed);
            }
    

    RunWorkerCompleted 中的 e.Error 是否包含 ex.Message?

    谢谢。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-09-24
      • 2012-08-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-11
      • 1970-01-01
      • 2018-10-19
      相关资源
      最近更新 更多