在BackgroundWorker中未处理的exception

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

后台操作会抛出偶尔的exception,通常是有人打开正在重新创build的文件。

无论代码是从IDE运行,还是不会popup错误对话框,通知用户发生了未处理的exception。 使用Releaseconfiguration编译代码也不会改变这一点。

根据MSDN :

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

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

BackgroundWorker是不是应该自动捕获这个错误? 这不是MSDN文档的内容吗? 我需要做什么来通知.NET这个错误正在被处理,同时仍然允许exception占用RunWorkerCompletedEventArgs的Error属性?

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

以下是一个certificateBackgroundWorker在DoWork中使用exception的小示例,并使它们在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(); 

我的心理debugging技巧向我揭示了你的问题:你正在访问RunWorkerCompleted处理程序中的e.Result – 如果有一个e.Error,你必须在不访问e.Result的情况下处理它。 例如,下面的代码是坏的,坏的,坏的,并且会在运行时抛出exception:

 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,你将不会收到运行时exception。

我将添加到MSDN文本 :

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

…和debugging器将报告exception为“〜exception是由用户代码未处理”

解决scheme:不要在debugging器下运行,并按预期工作:在e.Error中捕获到exception。

这是一个古老的问题,但我发现它同时谷歌search相同的症状。 发布这个以防其他人发现它的原因相同。

Judah的答案是正确的,但这不是“用户代码中未处理的exception”对话框出现的唯一原因。 如果在后台线程的构造函数中抛出一个exception,那么这个exception将立即导致对话,并且不会被传递给RunWorkerCompleted事件。 如果将有问题的代码移到任何构造函数之外(到其他任何方法),它将按预期工作。

[编辑]

犹大有一个伟大的观点。 我的例子指出了处理错误的具体情况,但是如果在DoWork方法中从来没有遇到exception,我的代码实际上会导致另一个exception。 这个例子是OK的,因为我们特别显示了BackgroundWorker的error handlingfunction。 但是,如果你没有检查错误参数对null,那么这可能是你的问题。

[/编辑]

我看不到相同的结果。 你可以发布一些代码吗? 这是我的代码。

 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.ComponentModel.BackgroundWorker.OnDoWork(DoWorkEventArgs e)系统上System.Exception:BOOM在BackgroundException.Form1.worker_DoWork(对象发件人,DoWorkEventArgs e)在D:\ Workspaces \ Sandbox \ BackgroundException \ BackgroundException \ Form1.cs: .ComponentModel.BackgroundWorker.WorkerThreadStart(Object argument)

一个有趣的文章,看起来类似于你的问题。 它有一个处理exception的部分。

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

我有同样的问题,我已经应用犹大答案之前,我发现这个话题后,一些谷歌search。

那么,犹大回答是部分正确的。 我在这里find了更好的答案

如果您在“真实世界”条件下运行应用程序,则debugging器正在良好地工作,RunWorkerCompleted按预期处理exception,应用程序行为也是预期的。

我希望这个答案有帮助。