【发布时间】:2013-03-20 05:47:14
【问题描述】:
动机
我在Windows.Forms 应用程序中使用Task,我想通过使用Task.ContinueWith() 和Control.Invoke() 在主UI 线程上重新引发任何异常来处理Task 引发的任何异常。
但是,如果我使用 Control.Invoke(),我无法注意到异常 - 但如果我使用 Control.BeginInvoke(),它会起作用。
有谁知道为什么它不能与Control.Invoke() 一起工作,以及如何让它工作?
解决方法
我目前使用Control.BeginInvoke()投掷而不是使用Control.Invoke()
复制步骤
环境:Windows 7 x64,Visual Studio 2012,为 .Net 4 编译(但 .Net 4.5 作为 VS2012 的一部分安装)。
(1) 使用名为 form1 的表单创建默认 Windows 窗体应用程序。
(2) 在表单上放置一个名为button1 的按钮,并为其添加一个名为button1_Click() 的处理程序。
(3) 实现button1_Click()如下:
private void button1_Click(object sender, EventArgs e)
{
Task.Factory.StartNew(() =>
{
Thread.Sleep(1000);
this.BeginInvoke(new Action(() =>
{
throw new InvalidOperationException("TEST");
}));
});
}
(4) 运行程序并单击按钮。一秒钟后,将显示一个异常对话框,如您所料。
(5) 现在将this.BeginInvoke 更改为this.Invoke。
(6) 再次运行程序并单击按钮。现在异常被静默忽略了!
Invoke() 和 BeginInvoke() 都在 UI 线程上为指定的 Control 执行,所以我不明白为什么在一种情况下会忽略异常,而在另一种情况下不会忽略异常...
我猜这一定与Control.Invoke() 如果抛出异常将永远不会返回的事实有关,但我的大脑很痛苦,试图弄清楚为什么这意味着异常(显然)被完全忽略了。
【问题讨论】:
-
啊哈!所以这就解释了。因此答案是:我不能使用
Control.Invoke;我必须使用Control.BeginInvoke。
标签: c# multithreading winforms exception