FileSystemWatcher和BackgroundWorker的全局错误处理程序

时间:2011-02-08 01:58:55

标签: error-handling backgroundworker global filesystemwatcher

我编写了一个包装FileSystemWatcher(fsw)的FileProcessor类,还有一个BackgroundWorker(bgw)线程来处理队列中的项目;

FileProcessor类从WPF应用程序中消耗掉;因此,WPF UI启动了fsw线程和bgw线程;

我不需要告诉WPF UI线程发生了错误,我需要的是确保fsw和bgw线程中的错误不会导致WPF UI崩溃(崩溃),这是我当前的问题

我处理了我所知道的错误,并且停止了崩溃,但我真正需要的是全局catch-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 UI中的一些消耗FileProcessor类以上的方法。

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

编辑:如果它是相关的,目前FileProcessor类和WPF UI在同一个Project(类型为Windows Application)中,但我打算将FileProcessor移动到它自己的类库项目中。

1 个答案:

答案 0 :(得分:2)

BackgroundWorker仅在其后台线程中运行一个事件:DoWork。如果DoWork引发异常,则会将其作为参数的一部分捕获并传递到RunWorkerCompleted。因此,由于DoWork中的未处理异常,BGW无法取消进程。

FileSystemWatcher处于略低的抽象层次。它通常会在ThreadPool上引发其事件。我认为事件处理程序不应该抛出异常(但是它们也不应该试图阻止所有异常):catch and handle vexing and exogenous exceptions, and allow boneheaded and fatal exceptions to crash the process。 IMO,忽略意外的异常是非常危险的。

如果您确实希望继续“忽略意外异常”路径,那么您可以采取一些方法。首先,您可以指定FileSystemWatcher.SynchronizingObject将其事件编组到WPF Dispatcher中。 WPF没有为此包含适当的对象,但您可以使用Nito.Async库中的GenericSynchronizingObject。一旦FSW将其事件封送到Dispatcher,您就可以使用Dispatcher.UnhandledException来处理来自Dispatcher上下文的任何异常。请注意,这可能包括一些非FSW的例外情况;特别是,它将包括在UI上下文中运行的任何事件,例如BackgroundWorker.RunWorkerCompleted

或者,您可以在app.config中设置“忽略所有ThreadPool例外”标记:

<legacyUnhandledExceptionPolicy enabled="1"/>

但我真的建议你不要这样做。它将捕获,写入控制台,然后忽略 ThreadPool个线程上的所有异常(如果将SynchronizingObject设置为null,则包括FSW事件处理程序)。这非常危险,因为您不知道例外是什么。这个标志是在.NET 2.0中引入的,人们可以更轻松地移植它们的.NET 1.0和.NET 1.1代码; .NET 4.0 still has the flag,但它是向后兼容性黑客,可能在将来的版本中消失。