很奇怪Application.ThreadException行为 [英] Very strange Application.ThreadException behaviour

查看:744
本文介绍了很奇怪Application.ThreadException行为的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用的是 Application.ThreadException 事件来处理,并在我的WinForms应用程序日志意外的异常。

I'm using the Application.ThreadException event to handle and log unexpected exceptions in my winforms application.

现在,在某个地方我的应用程序,我有以下code(或相当相当的东西,但这种虚$​​ C $ c是足以重现我的问题):

Now, somewhere in my application, I've got the following code (or rather something equivalent, but this dummy code is enough to reproduce my issue) :

            try
            {
                throw new NullReferenceException("test");
            }
            catch (Exception ex)
            {
                throw new Exception("test2", ex);
            }

我清楚地期待我Application_ThreadException处理程序也可以通过test2的异常,但情况并非总是如此。通常情况下,如果另一个线程乘警我的code到UI,我的处理程序接收测试的例​​外,就好像我没有在所有中招测试。

下面是一个简短的样本复制这种行为。我省略了设计师的code。

Here is a short sample reproducing this behavior. I have omitted the designer's code.

     static class Program
{
    [STAThread]
    static void Main()
    {
        Application.ThreadException += new System.Threading.ThreadExceptionEventHandler(Application_ThreadException);
        //Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException); // has no impact in this scenario, can be commented.

        AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);

        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new Form1());
    }

       static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
    {
        //this handler is never called
    }

    static void Application_ThreadException(object sender, System.Threading.ThreadExceptionEventArgs e)
    {
        Console.WriteLine(e.Exception.Message);
    }
}

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
        button1.Click+=new EventHandler(button1_Click);
    }

    protected override void OnLoad(EventArgs e) {
    System.Threading.Thread t = new System.Threading.Thread(new System.Threading.ThreadStart(ThrowEx));
    t.Start();
    }


    private void button1_Click(object sender, EventArgs e)
    {
        try
        {
            throw new NullReferenceException("test");
        }
        catch (Exception ex)
        {
            throw new Exception("test2", ex);
        }
    }

    void ThrowEx()
    {
        this.BeginInvoke(new EventHandler(button1_Click));
    }
}

该计划的我的电脑上的输出是:

The output of this program on my computer is :

test
... here I click button1
test2

我已经在.NET 2.0,3.5和4.0转载此。是否有人有一个合理的解释?

I've reproduced this on .net 2.0,3.5 and 4.0. Does someone have a logical explanation ?

推荐答案

还有这使得它很难调试发生了什么事情在你的code的错误:启动线程创建窗体的句柄之前。这将使BeginInvoke的失败。修正:

There's a bug in your code that makes it hard to debug what's going on: you start the thread before the form's Handle is created. That will make BeginInvoke fail. Fix:

    protected override void OnLoad(EventArgs e) {
        System.Threading.Thread t = new System.Threading.Thread(new System.Threading.ThreadStart(ThrowEx));
        t.Start();
    }

安美居,这是设计问题。在运行BeginInvoke的目标的Windows窗体code是这样的:

Anyhoo, this is designed behavior. The Windows Forms code that runs the BeginInvoke target looks like this:

  try
  {
      this.InvokeMarshaledCallback(tme);
  }
  catch (Exception exception)
  {
      tme.exception = exception.GetBaseException();
  }
  ...
       if ((!NativeWindow.WndProcShouldBeDebuggable && (tme.exception != null)) && !tme.synchronous)
       {
           Application.OnThreadException(tme.exception);
       }

这是exception.GetBaseException()调用搞砸了你的异常信息。为什么Windows窗体设计师选择这样做是不太清楚,我,还有与code的参考源无可奉告。我只能猜测,没有它除了会比较难以调试,在情况下,它提出的Windows窗体应用code水暖code来代替。不是一个很好的解释。

It is the exception.GetBaseException() call that screws up your exception message. Why the Windows Forms designers chose to do this isn't quite clear to me, there is no comment with the code in the Reference Source. I can only guess that without it the exception would be more difficult to debug, in case it is raised by the Windows Forms plumbing code instead of the application code. Not a great explanation.

他们已经表示,他们won't修复,也许你可以添加你的票。不要让你的希望。

They have already said that they won't fix it, perhaps you could add your vote. Don't get your hopes up.

解决方法是没有设置的InnerException。当然不是一个很好的选择。

The workaround is to not set the InnerException. Not a great option of course.

这篇关于很奇怪Application.ThreadException行为的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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