在另一个线程中引发异常时不调用UnhandledException [英] UnhandledException not called when exception thrown in another thread

查看:152
本文介绍了在另一个线程中引发异常时不调用UnhandledException的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

根据Microsoft文档,当线程(从线程池或使用System.Threading.Thread类创建的)上发生未处理的异常时,应为应用程序的默认AppDomain触发AppDomain.UnhandledException事件。这是MSDN 链接,在第二个注意部分之后进行了解释。

According to the Microsoft documentation, when an unhandled exception occurs on a thread (from either the thread pool or created using the System.Threading.Thread class) the AppDomain.UnhandledException event should fire for the default AppDomain of the application. Here is the MSDN link which explains it after the second NOTE section.

但是我无法重现此行为,据我从我的测试应用程序得知,它永远不会在默认的AppDomain或用于创建线程的AppDomain上触发UnhandledException。是文档错误还是我的测试代码?

But I cannot reproduce this behaviour, as far as I can tell from my test application it never fires the UnhandledException on either the default AppDomain or the AppDomain used to create the thread. Is the documentation wrong or my testing code?

using System;
using System.Runtime.ExceptionServices;
using System.Reflection;

public class Program
{
    static void Main()
    {
        Program.HookAppDomainExceptions();
        Test t = CreateTestInsideAppDomain("Nested1");
        t.SetupNested1();
        Console.ReadLine();
    }

    public static Test CreateTestInsideAppDomain(string appDomainName)
    {
        AppDomain nested1 = AppDomain.CreateDomain(appDomainName);
        string executingName = Assembly.GetExecutingAssembly().FullName;
        return (Test)nested1.CreateInstanceAndUnwrap(executingName, "Test");
    }

    public static void HookAppDomainExceptions()
    {
        AppDomain.CurrentDomain.FirstChanceException +=
            new EventHandler<FirstChanceExceptionEventArgs>(FirstChanceException);

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

    public static void FirstChanceException(object sender, FirstChanceExceptionEventArgs e)
    {
        Console.WriteLine("Domain:{0} FirstChanceException Handler",
                          AppDomain.CurrentDomain.FriendlyName);
    }

    public static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
    {
        Console.WriteLine("Domain:{0} UnhandledException Handler",
                          AppDomain.CurrentDomain.FriendlyName);
    }
}

public class Test : MarshalByRefObject
{
    private delegate void Nothing();

    public void SetupNested1()
    {
        var start = new Nothing(Nested1ThreadStart);
        start.BeginInvoke(null, null);
    }

    static void Nested1ThreadStart()
    {
        Program.HookAppDomainExceptions();
        Test t = Program.CreateTestInsideAppDomain("Nested2");
        t.SetupNested2();
    }

    public void SetupNested2()
    {
        Program.HookAppDomainExceptions();
        Test t = Program.CreateTestInsideAppDomain("Nested3");
        t.ThrowException();
    }

    public void ThrowException()
    {
        Program.HookAppDomainExceptions();
        throw new ApplicationException("Raise Exception");
    }
}


推荐答案

在您的代码 UnhandledException 不会在任何 AppDomain 上触发,因为如果您使用调用委托, BeginInvoke(),在执行期间引发的任何异常都将得到处理,然后在调用 EndInvoke()时将其重新抛出,而您不会这样做。

In your code UnhandledException isn't fired on any AppDomain, because if you call a delegate using BeginInvoke(), any exception that is thrown during its execution is handled and then rethrown when you call EndInvoke(), which you don't.

如果您调用 EndInvoke()

start.EndInvoke(start.BeginInvoke(null, null));

或同步执行委托:

start();

您会得到类似的结果: UnhandledException

You get similar results: UnhandledException of the main domain is raised.

如果相反,您按照文档中的说明进行操作,并使用 Thread 启动新线程类:

If instead, you do what the documentation says and start a new thread using the Thread class:

new Thread(Nested1ThreadStart).Start();

UnhandledException Nested1 和主应用程序域被引发。

UnhandledException of Nested1 and the main app domain are raised.

因此,回答您的问题:文档是正确的。您的代码是错误的。当您使用 BeginInvoke()异步调用委托时,应始终稍后再调用 EndInvoke()

So, to answer your question: The documentation is right. Your code is wrong. When you call delegate asynchronously using BeginInvoke(), you should always call EndInvoke() later.

这篇关于在另一个线程中引发异常时不调用UnhandledException的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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