Поймать System.Exception в потоке - PullRequest
1 голос
/ 04 апреля 2011

Я знаю, что не рекомендуется перехватывать System.Exception, если только он не на верхнем уровне приложения. Как насчет потока? Можно ли ловить System.Exception на верхнем уровне потока?

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

        while (Terminate == false)
        {
            var discoveryClient = new DiscoveryClient(new UdpDiscoveryEndpoint());

            try
            {
                var criteria = new FindCriteria(typeof(T));
                criteria.Scopes.Add(new Uri(Scope));
                var discovered = discoveryClient.Find(criteria);
                discoveryClient.Close();
                discoveryClient = null;

                // do something with the endpoints
            }
            catch (OutOfMemoryException e)
            {
                m_Logger.LogException(e, "Exception when trying to discover clients (Contract: {0})", typeof(T).Name);
                throw;
            }
            catch (Exception e)
            {
                m_Logger.LogException(e, "Exception when trying to discover clients (Contract: {0})", typeof(T).Name);

                if (discoveryClient != null)
                    (discoveryClient as IDisposable).Dispose();
            }

        }

Ответы [ 5 ]

3 голосов
/ 04 апреля 2011

Это зависит от того, что делает поток, и от контекста потока в вашем приложении.Вообще говоря, вы должны следовать золотому правилу: не поймайте исключение, если вы не знаете, как его обработать .(Я, конечно, упрощаю, но это практическое правило).

Поскольку речь идет о System.Exception, а не о каком-то подклассе, я предполагаю, что вы на самом деле не знаете, как обрабатывать исключение.Регистрация ошибки и разрешение завершению приложения (единственная законная причина перехватить исключение, которое вы не можете обработать) можно сделать без перехвата исключения из потока, который его вызвал, поэтому краткий ответ - нет, это не ОК .

Если я правильно помню, .NET 1 фактически перехватил и проглотил все исключения, возникшие в фоновых потоках.Это привело к тому, что в плохо написанных программах возникло так много проблем, что MS изменила поведение в .NET 2, чтобы исключить возможность сбоя приложения - и вы можете себе представить, что у них была очень веская причина для такого критического изменения.

Обновление, касающееся BackgroundWorker:

Пожалуйста, не принимайте модель использования BackgroundWorker за "глотание System.Exception в порядке".Вот что говорят документы для BackgroundWorker.RunWorkerCompleted:

Ваш обработчик событий RunWorkerCompleted должен всегда проверять свойства AsyncCompletedEventArgs.Error и AsyncCompletedEventArgs.Cancelled перед доступом к свойству RunWorkerCompletedEArgs.Если возникла исключительная ситуация или операция была отменена, доступ к свойству RunWorkerCompletedEventArgs.Result вызывает исключение.

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

2 голосов
/ 04 апреля 2011

Да - это отличная идея:)

Хмм, я не понимаю, почему люди предполагают, что не очень хорошая идея ловить исключения верхнего уровня. Серьезно, ты их не ловишь?

С точки зрения повседневной разработки, если ваш фоновый поток имеет исключение верхнего уровня, вы хотите знать об этом. Вы не хотите, чтобы приложение вылетало, поведение по умолчанию - пользователям это не нравится, как ни удивительно. Это одно из немногих мест, где вы определенно хотите ловить исключения и регистрировать / восстанавливать.

0 голосов
/ 04 апреля 2011

Обрабатывать только те исключения, с которыми вы могли бы что-то сделать.Чтобы не показывать желтый экран, я лично предпочитаю перехватывать unhandeld excetpion в событии global.asax Application_error

0 голосов
/ 04 апреля 2011

Официально это не очень хорошая практика, но иногда это делается.

Аргументы точно такие же, как и для этого в "основном" потоке.

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


Если вы решили пойти по этому пути, вы можете быть осторожны, чтобы исключить ThreadAbortException из своей ловли - это «ожидаемое исключение», если кто-либо когда-либо прерывает рабочий поток (что может или не может иметь место) в вашем приложении)

0 голосов
/ 04 апреля 2011

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

Так что если вы используете new Thread(), особенно в пользовательском интерфейсе, это будетхмурится.

Рекомендуется использовать BackgroundWorker или Task<T>, который инкапсулирует обработку исключений потока, поэтому не требуется никакой обработки исключений в терминах блока catch.


Эти 4 сценария являются приемлемыми случаями, когда вам нужен собственный поток (от CLR до C # ):

Я настоятельно рекомендую использовать пул потоков для выполнения асинхронных операций с привязкой к вычислениямкогда возможно.Однако в некоторых случаях вам может понадобиться явно создать поток, предназначенный для выполнения конкретной операции, связанной с вычислениями.Как правило, вы хотите создать выделенный поток, если вы собираетесь выполнять код, который требует, чтобы поток находился в определенном состоянии, которое не является нормальным для потока пула потоков.Например, я бы создал выделенный поток, если бы я хотел, чтобы поток выполнялся с особым приоритетом (все потоки пула потоков работают с обычным приоритетом, и вам не следует изменять приоритет потока пула потоков).Я бы также подумал о создании и использовании своего собственного потока, если бы я хотел сделать поток основным потоком (все потоки пула потоков являются фоновыми потоками), тем самым предотвращая умирание приложения до тех пор, пока мой поток не завершил свою задачу.Я бы также использовал выделенный поток, если бы задача, связанная с вычислениями, выполнялась очень долго;таким образом, я не стал бы облагать налогом логику пула потоков, поскольку он пытается выяснить, следует ли создавать дополнительный поток.Наконец, я бы использовал выделенный поток, если бы хотел запустить поток и, возможно, преждевременно прервать его, вызвав метод прерывания потока (см. Главу 21 «Хостинг и домены приложений CLR»).

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