BackgroundWorker中未处理的异常 [英] Unhandled exceptions in BackgroundWorker

查看:167
本文介绍了BackgroundWorker中未处理的异常的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个使用BackgroundWorker对象执行长时间运行的小型WinForms应用程序。



后台运行引发偶然异常,通常当某人有文件打开正在重新创建。



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



根据 MSDN


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


我希望有时会抛出这些异常,并希望在RunWorkerCompleted事件而不是在DoWork中处理它们。我的代码正常工作,并且在RunWorkerCompleted事件中正确处理错误,但是我不知道如何阻止.NET错误对话框抱怨发生未处理的异常。



BackgroundWorker是不是自动捕获该错误?这不是MSDN文档所说的吗?我需要做什么来通知.NET,这个错误正在处理,同时仍允许异常进入RunWorkerCompletedEventArgs的Error属性?

解决方案

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



以下是一些示例,证明BackgroundWorker在 DoWork 中享受例外情况,并将其提供给您在 RunWorkerCompleted 中:

  var worker = new BackgroundWorker(); 
worker.DoWork + =(sender,e)=>
{
throw new InvalidOperationException(哦shiznit!);
};
worker.RunWorkerCompleted + =(sender,e)=>
{
if(e.Error!= null)
{
MessageBox.Show(有一个错误!+ e.Error.ToString());
}
};
worker.RunWorkerAsync();

我的精神调试技巧向我显示了您的问题:您正在访问RunWorkerCompleted处理程序中的e.Result - 如果有一个e.Error,你必须处理它,而不用访问e.Result。例如,以下代码是坏的,坏的,坏的,并将在运行时抛出异常:

  var worker = new BackgroundWorker (); 
worker.DoWork + =(sender,e)=>
{
throw new InvalidOperationException(哦shiznit!);
};
worker.RunWorkerCompleted + =(sender,e)=>
{
// OH NOOOOOOOES!运行时异常,如果有
//错误,则无法访问e.Result。您可以使用e.Error检查错误。
var result = e.Result;
};
worker.RunWorkerAsync();

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

  private void RunWorkerCompletedHandler(object sender,RunWorkerCompletedEventArgs e)
{
if(e.Error == null)
{
DoSomethingWith(e.Result); //仅当没有发生错误时访问e.Result。
}
}

VOILA,您不会收到运行时异常。 / p>

I have a small WinForms app that utilizes a BackgroundWorker object to perform a long-running operation.

The background operation throws occasional exceptions, typically when somebody has a file open that is being recreated.

Regardless of whether the code is run from the IDE or not .NET pops up an error dialog informing the user that an Unhandled exception has occurred. Compiling the code using the Release configuration doesn't change this either.

According to MSDN:

If the operation raises an exception that your code does not handle, the BackgroundWorker catches the exception and passes it into the RunWorkerCompleted event handler, where it is exposed as the Error property of System.ComponentModel..::.RunWorkerCompletedEventArgs. If you are running under the Visual Studio debugger, the debugger will break at the point in the DoWork event handler where the unhandled exception was raised.

I expect these exceptions to be thrown on occasion and would like to handle them in the RunWorkerCompleted event rather than in DoWork. My code works properly and the error is handled correctly within the RunWorkerCompleted event but I can't for the life of me figure out how to stop the .NET error dialog complaining about the "Unhandled exception" from occurring.

Isn't the BackgroundWorker supposed to catch that error automagically? Isn't that what the MSDN documentation states? What do I need to do to inform .NET that this error is being handled while still allowing the exception to propage into the Error property of RunWorkerCompletedEventArgs?

解决方案

What you're describing is not the defined behavior of BackgroundWorker. You're doing something wrong, I suspect.

Here's a little sample that proves BackgroundWorker eats exceptions in DoWork, and makes them available to you in 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();

My psychic debugging skills are revealing your problem to me: You are accessing e.Result in your RunWorkerCompleted handler -- if there's an e.Error, you must handle it without accessing e.Result. For example, the following code is bad, bad, bad, and will throw an exception at runtime:

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();

Here's a proper implementation of the RunWorkerCompleted event handler:

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

VOILA, you won't receive runtime exceptions.

这篇关于BackgroundWorker中未处理的异常的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆