首页 文章

BackgroundWorker中未处理的异常

提问于
浏览
64

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

后台操作会抛出偶然的异常,通常是当有人打开正在重新创建的文件时 .

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

根据MSDN

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

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

那是什么MSDN文档说明了什么?我还需要做什么才能告知.NET正在处理此错误,同时仍然允许异常进入RunWorkerCompletedEventArgs的Error属性?

5 回答

  • 0

    我遇到了同样的问题,在谷歌用谷歌搜索之后找到这个话题之前我已经应用了犹大的答案 .

    嗯,犹大回答部分正确 . 我找到了一个更好的答案here

    调试器正在顺利运行,如果您在“真实条件”中运行应用程序,RunWorkerCompleted将按预期处理异常,并且应用程序行为也是预期的 .

    我希望这个答案有所帮助 .

  • 35

    您所描述的不是BackgroundWorker的已定义行为 . 我怀疑你做错了什么 .

    这是一个小样本,证明BackgroundWorker在 DoWork 中吃了异常,并在_1076814中使它们可用:

    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,您将不会收到运行时异常 .

  • 1

    我会添加到MSDN text

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

    ... AND the debugger will report the exception as "~Exception was unhandled by user code"

    解决方案:不要在调试器下运行并且它按预期工作:e.Error中捕获异常 .

  • 115

    这是一个老问题,但我在谷歌搜索时发现了相同的症状 . 发布此信息以防其他人因同样的原因找到它 .

    Judah 's answer is right, but it isn' t "unhandled exception in user code"对话框出现的唯一原因 . 如果从后台线程上的构造函数内部抛出异常,则该异常将立即导致该对话框,并且不会传递给RunWorkerCompleted事件 . 如果您将违规代码移到任何构造函数之外(对于任何其他方法),它将按预期工作 .

  • 2

    [编辑]

    犹大有一个很好的观点 . 我的例子指出了处理错误的细节,但是如果在DoWork方法中没有遇到异常,我的代码实际上会引起另一个异常 . 这个例子没问题,因为我们专门展示了BackgroundWorker的错误处理功能 . 但是,如果您没有针对null检查error参数,那么这可能是您的问题 .

    [/编辑]

    我没有看到相同的结果 . 你能发一点代码吗?这是我的代码 .

    private void Form1_Load(object sender, EventArgs e)
    {
        BackgroundWorker worker = new BackgroundWorker();
        worker.DoWork += new DoWorkEventHandler(worker_DoWork);
        worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(worker_RunWorkerCompleted);
        worker.RunWorkerAsync();
    }
    
    void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        // Will cause another exception if an exception didn't occur.
        // We should be checking to see if e.Error is not "null".
        textBox1.Text = "Error? " + e.Error;
    }
    
    void worker_DoWork(object sender, DoWorkEventArgs e)
    {
        for (int i = 0; i < 10; i++)
        {
            if (i < 5)
            {
                Thread.Sleep(100);
            }
            else
            {
                throw new Exception("BOOM");
            }   
        }
    }
    

    节目输出:

    错误? System.Exception:位于系统的System.ComponentModel.BackgroundWorker.OnDoWork(DoWorkEventArgs e)的D:\ Workspaces \ Sandbox \ BackgroundException \ BackgroundException \ Form1.cs中的BackgroundException.Form1.worker_DoWork(Object sender,DoWorkEventArgs e)中的BOOM .ComponentModel.BackgroundWorker.WorkerThreadStart(Object argument)

    一篇与您的问题类似的有趣文章 . 它有一个关于处理异常的部分 .

    http://www.developerdotstar.com/community/node/671

相关问题