在RunWorkerCompleted
事件中重新抛出异常时,我遇到了BackgroundWorker
或.NET框架的奇怪行为。RunWorkerCompleted未在主UI线程中执行?
发生在后台线程中的异常传递给RunWorkerCompleted
。在那里我做了一个object temp = e.Result
重新抛出异常。因为这应该发生在主UI线程中,所以我期望异常被传播到Application.Run(...)
,我用try-catch块包围它。
在Visual Studio中运行应用程序时,此工作正常。但是,当我在Visual Studio之外执行exe文件时,异常不会被处理并使应用程序崩溃。
难道RunWorkerCompleted
事件是而不是在主UI线程中执行?
这些职位不重复,而是确认我的情况是怪异:
- C# BackgroundWorker RunWorkerCompleted Event
- Events raised by BackgroundWorker not executed on expected thread
这是再现错误中有着非常简单的代码示例:创建WinForms项目并添加:
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
try
{
Form form = new Form();
form.Load += delegate
{
BackgroundWorker bw = new BackgroundWorker();
bw.DoWork += (sender, e) =>
{
// do nothing
};
bw.RunWorkerCompleted += (sender, e) =>
{
throw new Exception("Booo!");
};
bw.RunWorkerAsync();
};
Application.Run(form);
}
catch (Exception ex)
{
while (ex is TargetInvocationException && ex.InnerException != null)
ex = ex.InnerException;
MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
然后尝试:
- 在Visual Studio中运行它。在应用程序退出之前,您会收到一个友好的消息框。
- 在Visual Studio外运行编译的可执行文件。你会得到一个.NET框架“未处理的异常”消息。
有趣的部分是,如果我在2中点击“继续”,应用程序仍然存在,并显示窗体并接受用户输入。这意味着不是主UI线程,后台线程崩溃了。主线程仍然活着。 (为什么我想要做所有这些事情?我显示一个启动画面,并且一些应用程序启动工作在后台完成时,启动画面通过标签和进度条显示进度。必须创建并显示启动画面,然后获取主UI线程以启动BackgroundWorker
。在原始代码中,它将报告进度返回到更新启动窗体的主线程。如果在启动期间发生异常,我想要捕获它。在某些情况下,它们是“业务例外”,具有特定含义,例如“您无权使用此应用程序”。在这些情况下,我会在应用程序死前显示一个友好的消息框。此外,我有一个finally
块清理资源我不确定.NET框架“未处理的异常”对话框是否执行finally b在杀死应用程序之前锁定)。
你能制定一个问题吗? – 2010-10-22 14:49:49
@Pieter:我做了,它是粗体。 – chiccodoro 2010-10-22 14:50:32