Почему необработанное исключение в фоновом потоке не приводит к падению домена приложения? - PullRequest
15 голосов
/ 24 июня 2011

Я полностью озадачен. Я был настолько уверен, что .NET закрывает весь домен приложения, если в потоке есть неперехваченное исключение, которое я никогда не проверял.

Однако я только что попробовал следующий код, и он не выходит из строя ... Может кто-нибудь объяснить, почему?

(пробовал в .NET 4 и 3.5)

static void Main(string[] args)
{
    Console.WriteLine("Main thread {0}", Thread.CurrentThread.ManagedThreadId);

    Action a = new Action(() =>
    {
        Console.WriteLine("Background thread {0}", Thread.CurrentThread.ManagedThreadId);

        throw new ApplicationException("test exception");
    });

    a.BeginInvoke(null, null);

    Console.ReadLine();
}

Ответы [ 4 ]

9 голосов
/ 24 июня 2011

Это происходит из-за того, что BeginInvoke использует ThreadPool для внутреннего использования, а когда ThreadPool, любые неэкранированные исключения будут молчать.Тем не менее, если вы используете a.EndInvoke, то исключение будет выделено при методе EndInvoke.

Примечание: как указано João Angelo, что при использовании ThreadPool методов напрямую ", таких как ThreadPool.QueueUserWorkItems и UnsafeQueueUserWorkItem"выдаст исключения на уровне 2.0 и выше.

6 голосов
/ 24 июня 2011

С Исключения в управляемых потоках на MSDN:

В .NET Framework версии 2.0 среда выполнения общего языка позволяет большинству необработанных исключений в потоках выполняться естественным образом.В большинстве случаев это означает, что необработанное исключение приводит к завершению работы приложения.

Это значительное изменение по сравнению с .NET Framework версий 1.0 и 1.1, которое обеспечивает защиту для многих необработанных исключений, например, необработанных исключений.в потоках пула потоков.См. «Изменение из предыдущих версий» далее в этом разделе.

В качестве временной меры совместимости администраторы могут поместить флаг совместимости в раздел файла конфигурации приложения.Это заставляет общеязыковую среду выполнения вернуться к поведению версий 1.0 и 1.1.

<legacyUnhandledExceptionPolicy enabled="1"/>
3 голосов
/ 24 июня 2011

Обычно с асинхронными делегатами, если делегированный метод генерирует исключение, поток прерывается, и исключение будет снова выдано в вызывающем коде только при вызове EndInvoke.

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

Ранее я обычно говорил, потому что есть возможность заявить, что исключение следует игнорировать, еслиМетод делегата возвращает void.Для этого необходимо пометить метод атрибутом OneWay.

Если вы запустите следующий пример, вы получите исключение только при вызове willNotIgnoreThrow.EndInvoke.

static void Throws()
{
    Console.WriteLine("Thread: {0}", Thread.CurrentThread.ManagedThreadId);

    throw new ApplicationException("Test 1");
}

[OneWay]
static void ThrowsButIsIgnored()
{
    Console.WriteLine("Thread: {0}", Thread.CurrentThread.ManagedThreadId);

    throw new ApplicationException("Test 2");
}

static void Main(string[] args)
{
    Console.WriteLine("Main: {0}", Thread.CurrentThread.ManagedThreadId);

    var willIgnoreThrow = new Action(ThrowsButIsIgnored);
    var result1 = willIgnoreThrow.BeginInvoke(null, null);

    Console.ReadLine();
    willIgnoreThrow.EndInvoke(result1);

    Console.WriteLine("============================");

    var willNotIgnoreThrow = new Action(Throws);
    var result2 = willNotIgnoreThrow.BeginInvoke(null, null);

    Console.ReadLine();
    willNotIgnoreThrow.EndInvoke(result2);
}
0 голосов
/ 24 июня 2011

потому что исключение throw в данных потоках остается там, если оно не направлено обратно в основной поток.

Это то, что backgroundWorker делает для вас, если у вас есть исключение в потоке BackgroundWorker, оно перебрасывается в основной поток.

a.BeginInvoke(null, null);

это делает асинхронный вызов, который создает другой поток длявыполнить это

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...