Try / Catch and threading - PullRequest
       6

Try / Catch and threading

13 голосов
/ 22 апреля 2009

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

using System;
using System.Collections.Generic;
using System.Threading;

namespace TestCrash
{
    class Program
    {
        private static void Crash(object control)
        {
            AutoResetEvent are = (AutoResetEvent)(((object[])control)[0]);
            are.Set();
            throw new Exception("Burn baby burn");
        }
        static void Main(string[] args)
        {
            try
            {
                List<WaitHandle> waitHandles = new List<WaitHandle>();
                for (int i = 0; i < 100; i++)
                {
                    AutoResetEvent are = new AutoResetEvent(false);
                    waitHandles.Add(are);
                    object[] procControl = new object[] { are };
                    ThreadPool.QueueUserWorkItem(Crash, procControl);
                    WaitHandle.WaitAll(waitHandles.ToArray());
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
        }
    }
}

Я наивно думал, что, попробовав / поймав, я буду в безопасности, но я обнаружил, что это непросто (это сбой одного из моих сервисов).

Ответы [ 5 ]

28 голосов
/ 22 апреля 2009

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

Подумайте о задействованных стеках - когда выдается исключение, оно поднимается в стек до тех пор, пока не достигнет соответствующего блока перехвата. Новый поток имеет совершенно отдельный стек для создаваемого потока, поэтому он никогда не достигнет блока catch в стеке создаваемого потока.

РЕДАКТИРОВАТЬ: Конечно, вы могли бы спроектировать вашу систему так, чтобы поток создания сделал ожидание других событий - немного похоже на цикл сообщений в приложении Windows Forms. Новый поток может затем перехватить исключение и отправить сообщение в поток создания, который затем сможет обработать исключение. Это не нормальная настройка - вы должны делать все это явно.

2 голосов
/ 18 августа 2010

Попробуйте добавить это до вашего DoWork Sub

<System.Diagnostics.DebuggerNonUserCodeAttribute()> _

Я использую фоновый рабочий, и все Try Catch в моем цикле работают так, как вы ожидаете от них.

2 голосов
/ 22 апреля 2009

Возможно, вы захотите использовать обертку EventGeneratingThread - это позволит вам отлавливать и обрабатывать исключения, возникающие в потоках процесса, который их породил.

2 голосов
/ 22 апреля 2009

Работающий поток не будет перехвачен в вашем операторе try / catch, поскольку он выполняется в другом потоке. Try / Catch работает только для текущего потока. То, что вам нужно сделать, - это попробовать / перехватить функцию, выполняемую потоком, и каким-то образом управлять тем, что происходит в случае сбоя.

2 голосов
/ 22 апреля 2009

Плохо делать предположения, особенно когда речь идет о нескольких потоках (вы знаете эту старую поговорку).

Почему может код, запустивший поток, увидеть исключение? Код, который запустил поток, может даже не существовать, когда генерируется исключение.

...