- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
在 RunWorkerCompleted
事件中重新抛出异常时,我遇到了 BackgroundWorker
或 .NET 框架的奇怪行为。
后台线程中发生的异常被传递给RunWorkerCompleted
。我在那里做了一个 object temp = e.Result
来重新抛出异常。由于这应该发生在主 UI 线程中,我希望异常传播到 Application.Run(...)
,我用 try-catch block 将其包围。
在 Visual Studio 中运行应用程序时,这工作正常。但是,当我在 Visual Studio 外部执行 exe 文件时,异常未得到处理并导致应用程序崩溃。
会不会是 RunWorkerCompleted
事件没有在主 UI 线程中执行?
这些帖子不是重复的,而是确认我的情况很奇怪:
这是一个重现错误的极其简化的代码示例:创建一个 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);
}
}
然后尝试:
有趣的是,如果我在 2 中点击“继续”,应用程序会继续存在,显示表单并接受用户输入。这一定意味着崩溃的不是主 UI 线程,而是后台线程。主线程仍然存在。
(为什么我要做这些事情?我显示一个闪屏,虽然一些应用程序启动工作是在后台完成的,但闪屏通过标签和进度条显示进度。所以我有创建并显示启动画面,然后获取主 UI 线程以启动 BackgroundWorker
。在原始代码中,它向主线程报告进度,主线程更新启动画面。如果在启动期间发生异常, 我想捕获它。在某些情况下,它们是具有特定含义的“业务异常”,例如“您无权使用此应用程序”。在这些情况下,我会在让应用程序死掉之前显示一个友好的消息框。此外,我还有一个 finally
block 来清理资源。我不确定 .NET 框架“未处理的异常”对话框是否在终止应用程序之前执行了 finally block 。)
最佳答案
在 Application.Run() 中的消息循环代码周围有一个 try/catch block ,用于捕获事件处理程序引发的未处理异常。 catch 子句引发 Application.ThreadException 事件。该事件有一个默认处理程序,它显示一个 ThreadExceptionDialog。为用户提供忽略错误或中止程序的选项。
当您使用调试器运行程序时,此 catch 子句将被禁用。这使您可以轻松调试异常。禁用它后,CLR 将在您的 Main() 方法中找到 catch 子句。要禁用此行为,请将这行代码添加到 Main() 方法的顶部:
Application.SetUnhandledExceptionMode(UnhandledExceptionMode.ThrowException);
它现在的行为方式与在调试器中的行为方式相同。此处更好的捕鼠器是为 AppDomain.CurrentDomain.UnhandledException 实现事件处理程序。这会捕获所有未处理的异常,包括在工作线程中引发的异常。并允许您调试未处理的异常,调试器在 throw 语句处停止。
关于c# - RunWorkerCompleted 没有在主 UI 线程中执行?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3997856/
我是一名优秀的程序员,十分优秀!