我正在使用BackgroundWorker,因为我需要在我的UI中提供反馈。我还需要在我的类中使用ThreadPool才能以异步方式运行,但似乎我的后台工作程序无法捕获它抛出的异常。
它旨在就其正在执行的任务提供反馈。
我做了一个简单的应用程序来重现问题:
// MAIN UI CLASS
BackgroundWorker _bgWorker = new BackgroundWorker();
void _bgWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if (e.Error != null)
{
// Returns custom error
MessageBox.Show(e.Error.Message);
}
}
void _bgWorker_DoWork(object sender, DoWorkEventArgs e)
{
try {
// Initialize test error class
var testClass = new TestClass();
}
catch (Exception ex)
{
MessageBox.Show("im from trycatch");
}
}
private void Window_ContentRendered(object sender, EventArgs e)
{
_bgWorker.DoWork += _bgWorker_DoWork;
_bgWorker.RunWorkerCompleted += _bgWorker_RunWorkerCompleted;
}
/////////////////////////////////////////////////////////////////////////
// TEST ERROR CLASS
public TestClass()
{
throw new Exception("im a custom error");
}
这样可以。使用try-catch,它会捕获try-catch处理的错误。然而,如果没有try-catch,它会在RunWorkerCompleted中处理它。
但是,我真的需要这些方法异步(这就是我使用ThreadPool的原因),但调试器始终指向异常。 (当我在没有调试器的情况下尝试时它只会崩溃程序)
// TEST ERROR CLASS
public TestClass()
{
ThreadPool.QueueUserWorkItem(delegate
{
throw new Exception("im a custom error");
}
}
我尝试使用try-catch语句重新抛出错误(希望它将异常传递给BackgroundWorker),但它不起作用。
希望你能帮助我。 提前谢谢。答案 0 :(得分:0)
您不需要从DoWork方法将代码放在ThreadPool上。当您致电_bgWorker_DoWork
时,BackgroundWorker将自动在ThreadPool线程上引发RunWorkerAsync()
方法。
如果你试图从你的后台工作者那里开始几个更多的ThreadPool任务,那么我想这可能是一个考虑因素,但在这种情况下我会建议在.NET4中使用TPL,如果可能的话......
http://msdn.microsoft.com/en-us/library/dd460717(v=vs.110).aspx
如果你不能使用TPL,那么你必须将ThreadPool代码包装在TryCatch中,并将Exception放在可以在该方法之外访问的地方。
例如,在您的UI类中添加internal static List<Exception> backgroundExceptions;
成员,后台工作者添加此列表中的任何捕获的异常,然后您必须在后台工作完成后调查此列表,以查看是否存在任何异常
这基本上就是TPL正在为你做的事情......给你一个“观察”后台线程上发生的异常的地方,但你仍然有责任在{{1}中寻找那些例外。通过调用将为您重新抛出异常的方法。