UnhandledException не вызывается, когда исключение выдается в другом потоке - PullRequest
8 голосов
/ 11 сентября 2011

Согласно документации Microsoft, когда в потоке возникает необработанное исключение (из пула потоков или созданное с использованием класса System.Threading.Thread), событие AppDomain.UnhandledException должно запускаться для AppDomain по умолчанию приложения.Вот MSDN ссылка , которая объясняет это после второго раздела NOTE.

Но я не могу воспроизвести это поведение, насколько я могу судить по моему тестовому приложению, оно никогда не запускает UnhandledException ни на одном из них.AppDomain по умолчанию или AppDomain, используемый для создания потока.Документация неверна или мой тестовый код?

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

Ответы [ 2 ]

11 голосов
/ 11 сентября 2011

В вашем коде UnhandledException не запускается ни на одном AppDomain, потому что если вы вызываете делегата с использованием BeginInvoke(), любое исключение, которое выдается во время его выполнения, обрабатывается и затем перебрасывается при вызове EndInvoke(), что вы не делаете.

Если вы позвоните EndInvoke():

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

или выполнить делегат синхронно:

start();

Вы получаете похожие результаты: UnhandledException основного домена поднято.

Если вместо этого вы делаете то, что написано в документации, и запускаете новый поток, используя класс Thread:

new Thread(Nested1ThreadStart).Start();

UnhandledException из Nested1 и основной домен приложения подняты.

Итак, чтобы ответить на ваш вопрос: документация верна. Ваш код неверен. Когда вы вызываете делегат асинхронно, используя BeginInvoke(), вы всегда должны вызывать EndInvoke() позже.

0 голосов
/ 11 сентября 2011

У меня тоже была эта проблема.Я использовал Шаблон наблюдателя , чтобы решить это.вы можете реализовать интерфейс в своем классе вызывающих, у которого есть метод, который вызывает другой поток, когда происходит исключение.

Вот ссылка, которая показывает, как реализовать этот шаблон Исследование шаблона проектирования Observer

...