Глобальный обработчик ошибок для FileSystemWatcher и BackgroundWorker - PullRequest
2 голосов
/ 08 февраля 2011

Я написал класс FileProcessor, который обертывает FileSystemWatcher (fsw), а также имеет поток BackgroundWorker (bgw) для обработки элементов в очереди;

Класс FileProcessor используется из приложения WPF; таким образом, пользовательский интерфейс WPF запускает как потоки fsw, так и потоки bgw;

Мне не нужно сообщать потоку пользовательского интерфейса WPF, что произошли ошибки, мне нужно, чтобы ошибки в потоках fsw и bgw не приводили к сбою (сбоям) пользовательского интерфейса WPF, что является моей текущей проблемой. .

Я обработал ошибки, о которых я знаю, и это остановило сбой, но что мне действительно нужно, так это глобальные универсальные обработчики ошибок для объектов fsw и bgw, которые (молча) игнорируют любые неожиданные ошибки. Есть ли такая вещь?

public class FileProcessor
{
     private FileSystemWatcher _fsw;
     private BackgroundWorker _bgw;


     //constructor
    public FileProcessor()
        {
        //initialize
        _bgThread = new BackgroundWorker();
        _fsw = new FileSystemWatcher();

        _fsw.Created += new FileSystemEventHandler(fsw_OnCreated);
        _fsw.Error += new ErrorEventHandler(fsw_OnError);
        //... etc.

        }


        public void StartAsync()
        {
        _fsw.EnableRaisingEvents = true; //start fsw on its own thread     
        _bgThread.RunWorkerAsync(); //start bgw on its own thread

        //... etc

        }

        private void fsw_OnCreated(object sender, FileSystemEventArgs e)
        {

              //local error handler;
              try
              {
                 DoStuff();
              }
              catch (Exception ex)
              {
                 MessageBox.Show(ex.Message);
              }
        }


    void fsw_OnError(object sender, ErrorEventArgs e)
     {

          //THIS EVENT NEVER FIRED OnError from DoStuff() when i didn't have try/catch around DoStuff() ! 
          //so it seems it's not meant to handle all Global errors from fsw.
          MessageBox.Show(e.GetException().Message);
     }


     //What i want are Global Error Handlers so that _fsw does not bring down the UI!; 
     //Ditto for _bgw


} //end FileProcessor class

... и некоторый метод в пользовательском интерфейсе WPF, который использует вышеуказанный класс FileProcessor.

FileProcessor _processor = new FileProcessor() //form level.
private void btnButtonStart_Click(object sender, RoutedEventArgs e)
{
   _processor.StartAsync();
}

РЕДАКТИРОВАТЬ: если это уместно, в настоящее время класс FileProcessor и пользовательский интерфейс WPF находятся в одном проекте (типа приложения Windows), но я намерен переместить FileProcessor в свой собственный проект библиотеки классов.

1 Ответ

2 голосов
/ 20 февраля 2011

BackgroundWorker запускает только одно событие в фоновом потоке: DoWork.Если DoWork вызывает исключение, то оно перехватывается и передается как часть аргумента в RunWorkerCompleted.Таким образом, для BGW невозможно отключить процесс из-за необработанного исключения в DoWork.

FileSystemWatcher находится на несколько более низком уровне абстракции.Обычно он вызывает свои события на ThreadPool.Я придерживаюсь мнения, что обработчики событий просто не должны генерировать исключения (но при этом они не должны пытаться предотвращать все исключения): ловит и обрабатывает неприятные и экзогенные исключения, а также допускает фатальные и фатальные исключения, приводящие к сбою процесса .ИМО, игнорировать неожиданные исключения очень опасно.

Если вы хотите продолжить путь «игнорировать неожиданные исключения», то есть несколько подходов, которые вы можете использовать.Во-первых, вы можете назначить FileSystemWatcher.SynchronizingObject для маршалинга его событий в WPF Dispatcher.WPF не включает соответствующий объект для этого, но вы можете использовать GenericSynchronizingObject из библиотеки Nito.Async .После того, как FSW отправит свои события в Dispatcher, вы можете использовать Dispatcher.UnhandledException для обработки любых исключений из контекста Dispatcher.Обратите внимание, что это может включать некоторые исключения, которые не из FSW;в частности, он будет включать любые события, которые выполняются в контексте пользовательского интерфейса, такие как BackgroundWorker.RunWorkerCompleted.

В качестве альтернативы, вы можете установить флаг «игнорировать все ThreadPool исключения» в вашемapp.config:

<legacyUnhandledExceptionPolicy enabled="1"/>

Однако я действительно рекомендую вам не делать этого.Он будет перехватывать, записывать в консоль, а затем игнорировать все исключения в потоках ThreadPool (включая обработчики событий FSW, если вы оставите для SynchronizingObject значение null).Это очень опасно, так как вы не знаете, что такое исключения.Этот флаг был введен в .NET 2.0, чтобы людям было проще переносить их код .NET 1.0 и .NET 1.1;.NET 4.0 все еще имеет флаг , но это хак с совместимостью обратной , который может исчезнуть в будущей версии.

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