我正在使用应用程序线程异常 http://msdn.microsoft.com/en-us/library/system.windows.forms.application.threadexception.aspx事件来处理和记录我的 winforms 应用程序中的意外异常。
现在,在我的应用程序中的某个地方,我有以下代码(或者更确切地说是等效的代码,但这个虚拟代码足以重现我的问题):
try
{
throw new NullReferenceException("test");
}
catch (Exception ex)
{
throw new Exception("test2", ex);
}
我显然希望我的 Application_ThreadException 处理程序能够传递“test2”异常,但情况并非总是如此。通常,如果另一个线程将我的代码编组到 UI,我的处理程序会收到“test”异常,就像我根本没有捕获“test”一样。
这是重现此行为的简短示例。我省略了设计师的代码。
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));
}
}
该程序在我的计算机上的输出是:
test
... here I click button1
test2
我在 .net 2.0、3.5 和 4.0 上重现了这个。有人有一个合乎逻辑的解释吗?