如何使用Control.Invoke()抛出不会被忽略的异常? [英] How can I use Control.Invoke() to throw an exception that won't be ignored?

查看:125
本文介绍了如何使用Control.Invoke()抛出不会被忽略的异常?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

动机



我在<$ c中使用任务 $ c> Windows.Forms 应用程序,其中我想使用 Task.ContinueWith()处理由 Task 抛出的任何异常) Control.Invoke()重新启动主UI线程上的任何异常。



但是,如果我使用 Control.Invoke() - 但如果我使用 Control,它将起作用,我无法得到异常。 BeginInvoke()



有人知道为什么它不适用于 Control.Invoke(),以及如何让它工作?



解决方法



我正在使用 Control.BeginInvoke()而不是使用 Control.Invoke()



重现步骤



ENVIRONMENT:Windows 7 x64,Visual Studio 2012,已编译。 Net 4(但.Net 4.5作为VS2012的一部分安装)。



(1)Cre吃一个名为 form1 的默认Windows窗体应用程序。



(2)将一个按钮放在名为 button1 ,并添加一个名为 button1_Click()的处理程序。


$ b $ (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() / code>在UI线程上执行指定的 Control ,所以我不明白为什么在一种情况下,异常被忽略,而另一种则不是忽略...



我猜这是与$ code> Control.Invoke()永远不会返回,如果它引发异常,但我的大脑痛苦试图解决为什么这意味着异常(显然)完全被忽视。

解决方案

这是按照设计,Invoke()处理与BeginInvoke()不同的异常。它将会将异常编组并重新抛出,以便您知道调用的方法失败。因为线程已经移动了,所以它不能为BeginInvoke()工作,所以它在UI线程上被引发。接下来的问题是Task类会使用异常,所以你不会看到它。



你这样做很困难。如果你喜欢默认的异常对话框,那么只需使用它来提升异常:

  this.BeginInvoke(new Action )=> {
using(var dlg = new ThreadExceptionDialog(new InvalidOperationException(TEST))){
dlg.ShowDialog();
Environment.Exit(1);
}


Motivation

I'm using a Task in a Windows.Forms application where I want to handle any exceptions thrown by the Task by using Task.ContinueWith() and Control.Invoke() to rethrow any exceptions on the main UI thread.

However, I couldn't get the exception to be noticed if I use Control.Invoke() - but it works if I use Control.BeginInvoke().

Does anyone know why it doesn't work with Control.Invoke(), and how to get it to work?

Workaround

I'm currently using Control.BeginInvoke() to throw instead of using Control.Invoke()

Steps to reproduce

ENVIRONMENT: Windows 7 x64, Visual Studio 2012, Compiled for .Net 4 (but .Net 4.5 is installed as part of VS2012).

(1) Create a default Windows Forms app with a form called form1.

(2) Put a button on the form called button1, and add a handler for it called button1_Click().

(3) Implement button1_Click() as follows:

private void button1_Click(object sender, EventArgs e)
{
    Task.Factory.StartNew(() =>
    {
        Thread.Sleep(1000);
        this.BeginInvoke(new Action(() =>
        {
            throw new InvalidOperationException("TEST");
        }));
    });
}

(4) Run the program and click the button. After a second, an exception dialog is displayed as you would expect.

(5) Now change this.BeginInvoke to this.Invoke.

(6) Run the program again and click the button. Now the exception is silently ignored!

Both Invoke() and BeginInvoke() execute on the UI thread for the specified Control, so I can't understand why in one case the exception is ignored and in the other it is not ignored...

I'm guessing it must be something to do with the fact that Control.Invoke() will never return if it throws an exception, but my brain hurts trying to work out why that would mean the exception is (apparently) totally ignored.

解决方案

This is by design, Invoke() handles exceptions differently than BeginInvoke(). It will marshal the exception back and re-throw it so that you know that the invoked method failed. This cannot work for BeginInvoke() since the thread has moved on already, so it is raised on the UI thread. The next problem is that the Task class swallows exceptions so you never see it.

You are doing this the hard way. If you like the default exception dialog then just use it with raising an exception at all:

this.BeginInvoke(new Action(() => {
    using (var dlg = new ThreadExceptionDialog(new InvalidOperationException("TEST"))) {
        dlg.ShowDialog();
        Environment.Exit(1);
    }

这篇关于如何使用Control.Invoke()抛出不会被忽略的异常?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆