一尘不染

BackgroundWorker中未处理的异常

c#

我有一个小型WinForms应用程序,该应用程序利用BackgroundWorker对象执行长时间运行的操作。

后台操作偶尔会引发异常,通常是当有人打开了正在重新创建的文件时。

不管代码是否从IDE运行,.NET都会弹出一个错误对话框,通知用户发生了未处理的异常。使用Release配置编译代码也不会对此进行更改。

根据MSDN

如果该操作引发了代码无法处理的异常,则BackgroundWorker将捕获该异常并将其传递到RunWorkerCompleted事件处理程序,在该事件处理程序中将其公开为System.ComponentModel
.. ::。RunWorkerCompletedEventArgs的Error属性。如果您在Visual
Studio调试器下运行,则调试器将在DoWork事件处理程序中引发未处理异常的点处中断。

我希望有时会抛出这些异常,并且希望在RunWorkerCompleted事件中而不是在DoWork中处理它们。我的代码正常运行,并且在RunWorkerCompleted事件中正确处理了错误,但是我终生无法弄清楚如何停止抱怨“未处理的异常”的.NET错误对话框。

BackgroundWorker是否应该自动捕获该错误?这不是MSDN文档说明的吗?我需要做什么做的通知.NET,这个错误
被处理,同时仍允许例外propage到RunWorkerCompletedEventArgs的错误属性?


阅读 569

收藏
2020-05-19

共1个答案

一尘不染

您所描述的不是BackgroundWorker的已定义行为。我怀疑您做错了。

这是一个小示例,证明BackgroundWorker在 DoWork中 吃了异常,并在 RunWorkerCompleted
中将它们提供给您:

var worker = new BackgroundWorker();
worker.DoWork += (sender, e) => 
    { 
        throw new InvalidOperationException("oh shiznit!"); 
    };
worker.RunWorkerCompleted += (sender, e) =>
    {
        if(e.Error != null)
        {
            MessageBox.Show("There was an error! " + e.Error.ToString());
        }
    };
worker.RunWorkerAsync();

我的心理调试技能向我揭示了您的问题:您正在RunWorkerCompleted处理程序中访问e.Result
-如果出现e.Error,则必须在不访问e.Result的情况下进行处理。例如,以下代码不好,不好,不好,并且会在运行时引发异常:

var worker = new BackgroundWorker();
worker.DoWork += (sender, e) => 
    { 
        throw new InvalidOperationException("oh shiznit!"); 
    };
worker.RunWorkerCompleted += (sender, e) =>
    {
        // OH NOOOOOOOES! Runtime exception, you can't access e.Result if there's an
        // error. You can check for errors using e.Error.
        var result = e.Result; 
    };
worker.RunWorkerAsync();

这是RunWorkerCompleted事件处理程序的正确实现:

private void RunWorkerCompletedHandler(object sender, RunWorkerCompletedEventArgs e)
{
    if (e.Error == null)
    {
       DoSomethingWith(e.Result); // Access e.Result only if no error occurred.
    }
}

VOILA,您将不会收到运行时异常。

2020-05-19