簡體   English   中英

在另一個線程中拋出異常時未調用UnhandledException

[英]UnhandledException not called when exception thrown in another thread

根據Microsoft文檔,當線程(來自線程池或使用System.Threading.Thread類創建)發生未處理的異常時,應觸發AppDomain.UnhandledException事件以獲取應用程序的默認AppDomain。 這是MSDN 鏈接 ,它在第二個注釋部分之后解釋它。

但我無法重現這種行為,據我所知,從我的測試應用程序中它永遠不會在默認的AppDomain或用於創建線程的AppDomain上觸發UnhandledException。 文檔是錯的還是我的測試代碼?

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");
    }
}

在你的代碼中,不會在任何AppDomain上觸發UnhandledException ,因為如果使用BeginInvoke()調用委托,則在執行期間拋出的任何異常都會被處理,然后在調用EndInvoke()時重新拋出,而不是。

如果你要么調用EndInvoke()

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

或同步執行委托:

start();

您得到類似的結果:引發主域的UnhandledException

相反,如果您執行文檔所說的操作並使用Thread類啟動新線程:

new Thread(Nested1ThreadStart).Start();

Nested1 UnhandledException和主app域。

那么,回答你的問題:文檔是正確的。 你的代碼錯了。 使用BeginInvoke()異步調用委托時,應始終稍后調用EndInvoke()

我也有這個問題。 我使用Observer Pattern來解決這個問題。 您可以在調用者類中實現一個接口,該接口具有一個在發生異常時從另一個線程調用的方法。

這是一個鏈接,顯示如何實現此模式探索觀察者設計模式

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM