gpt4 book ai didi

c# - 非常奇怪的 Application.ThreadException 行为

转载 作者:太空狗 更新时间:2023-10-29 17:51:19 31 4
gpt4 key购买 nike

我正在使用 Application.ThreadException在我的 winforms 应用程序中处理和记录意外异常的事件。

现在,在我的应用程序中的某个地方,我得到了以下代码(或者更确切地说,是一些等效的代码,但这个虚拟代码足以重现我的问题):

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

我显然希望我的 Application_ThreadException 处理程序通过“test2”异常,但情况并非总是如此。通常,如果另一个线程将我的代码编码到 UI,我的处理程序会收到“测试”异常,就像我根本没有捕获到“测试”一样。

这是一个重现此行为的简短示例。我省略了设计者的代码。

     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 上复制了这个。有人有合乎逻辑的解释吗?

最佳答案

您的代码中存在一个错误,这使得调试正在发生的事情变得困难:您在创建表单的句柄之前启动了线程。这将使 BeginInvoke 失败。修复:

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

无论如何,这是设计好的行为。运行 BeginInvoke 目标的 Windows 窗体代码如下所示:

  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 窗体设计者选择这样做对我来说不是很清楚,引用源中的代码没有评论。我只能猜测,如果没有它,异常将更难调试,以防它是由 Windows 窗体管道代码而不是应用程序代码引发的。不是很好的解释。

他们已经说过他们won't fix it ,也许您可​​以投票。不要抱太大希望。

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

关于c# - 非常奇怪的 Application.ThreadException 行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3007066/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com