Подтвердить что ты не робот

Выбрасывание исключений в методе обратного вызова для таймеров

Я не смог найти ответ на этот вопрос где угодно...

Что происходит с исключениями, вызванными методом обратного вызова для System.Threading.Timer(или в обработчике событий для System.Timers.Timer). Является ли исключение распространенным в потоке, на котором был создан таймер или потерялся ли исключение?

Каковы побочные эффекты бросания исключения в функции обратного вызова таймера?

Каким будет правильный способ оповестить поток создания таймера о том, что было создано исключение в рабочем потоке (метод обратного вызова)?

Спасибо за ваше время.

4b9b3361

Ответ 1

Исключение не передается обратно вызывающему потоку. Если вы хотите, чтобы это было, вы можете добавить блок catch и выяснить способ оповещения о вызывающем потоке. Если вызывающий поток представляет собой поток WinForms или WPF UI, вы можете использовать класс SynchronizationContext для передачи вызова в поток пользовательского интерфейса. В противном случае вы можете использовать потокобезопасную очередь (или блокировку синхронизации) и периодически проверять ее в другом потоке.

System.Timers.Timer тихо проглатывает исключения и продолжает таймер (хотя это может быть изменено в будущих версиях фреймворка); System.Threading.Timer завершает работу программы.

Ответ 2

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

Необработанные исключения в потоке (System.Threading.Timer) остановят всю вашу программу.

Ответ 3

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

EventHolderCallingClass: он должен определить делегат и событие, как показано ниже.

public class EventHolderCallingClass
{    
  public delegate void HandleExceptionEventDelegate(Exception exception);
  public event HandleExceptionEventDelegate HandleExceptionEvent ;

  void Timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
  {
    try
    {
      //some operation which caused exception.
    }
    catch(Exception exception)
    {
      if(HandleExceptionEvent!=null)
        HandleExceptionEvent(exception) 
    }
  }
}

Класс обработчика событий (обработчик исключений):

    public EventHandlerClassConstructor()
    {
            EventHolderCallingClass.HandleExceptionEvent += new EventHolderCallingClass.HandleExceptionEventDelegate(HandleExceptionEventHandler);            
    }

    void HandleExceptionEventHandler(Exception exception)
    {
        //handle exception here.
    }