我编写了一个包装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移动到它自己的类库项目中。
答案 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,但它是向后兼容性黑客,可能在将来的版本中消失。