如何处理BackgroundWorker线程中的exception?
在WPF应用程序中,我有一个有计算机的数据库访问任务,由计时器定期运行,此任务已在BackgroundWorker线程中执行。
当连接尝试失败时,我通过try_catch
构造引发exception,我想更新UI线程中的状态栏文本。
在BackgroundWorker
是否有一些prebuild事件构造用于实现它,比如DoWorkEventHandler
或RunWorkerCompletedEventHandler
,可以用于此吗? 如果没有,怎么做得更好?
编辑(补充):
如果我想在RunWorkerCompletedEventHandler
处理exception,使用e.Error
参数,它不起作用。 如果我在BackgroundWorker
线程中保留未处理的exception,则应用程序挂起并且调试器指向在BackgroundWorker
线程内部执行的代码字符串,并说: 用户代码未处理exception 。
因此,在这种情况下,线程不会停止,向RunWorkerCompletedEventHandler
发出信号,表示它因错误而停止,但整个应用程序停止工作。
可以使用Dispatcher.BeginInvoke从后台线程更新WPF UI。
例如,如果您的后台代码是Window的一部分,那么您可以更新TextBlock:
this.Dispatcher.BeginInvoke((Action)(() => { textBlock.Text = "Connection Failed!"; }));
编辑:
如果您的后台代码位于Window以外的类中,您可以创建一个界面来帮助:
public interface IShowStatus { void ShowStatus(string message); }
在Window中实现接口
public void ShowStatus(string message) { this.Dispatcher.BeginInvoke((Action)(() => { textBlock.Text = message; })); }
在您的类中,后台工作者创建一个属性来保存对接口的引用。
public IShowStatus StatusDisplay { get; set; }
在Window类中初始化背景类。
public void InitBackground() { BackgroundClass background = new BackgroundClass(); background.StatusDisplay = this; ...
最后在你的后台主题中你可以说:
StatusDisplay.ShowStatus("Connection Failed!");
RunWorkerCompletedEventArgs e
的RunWorkerCompletedEventHandler
包含属性Error
它的类型为Exception。 如果在后台线程的工作期间没有发生exception,则prpery的值为null。 否则它包含发生的错误。
private void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { Exception exceptionThrowDuringDoWorkEventHandler = e.Error; }
将后台worker的WorkerReportsProgress属性设置为true ,然后为事件ProgressChanged添加事件处理程序。 在下面的代码中,我还为Form.Load添加了一个事件处理程序。
现在尝试以下代码:
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e) { MessageBox.Show(e.UserState.ToString()); } private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) { try { //some code that throws an exception throw new NotImplementedException(); } catch (Exception ex) { backgroundWorker1.ReportProgress(0/*percent of progress*/, ex); } } private void Form1_Load(object sender, EventArgs e) { backgroundWorker1.RunWorkerAsync(); }
如果我想在
RunWorkerCompletedEventHandler
处理exception,使用e.Error
参数,它不起作用。 如果我在BackgroundWorker
线程中保留未处理的exception,则应用程序挂起并且调试器指向在BackgroundWorker
线程内部执行的代码字符串,并说: 用户代码未处理exception 。因此,在这种情况下,线程不会停止,向
RunWorkerCompletedEventHandler
发出信号,表示它因错误而停止,但整个应用程序停止工作。
我对此非常好奇。 尝试在控制台应用程序中运行以下代码,看看程序是否崩溃或者错误是否显示在RunWorkerCompletedEventArgs
。
static void Main(string[] args) { var bw = new BackgroundWorker(); bw.DoWork += Bw_DoWork; bw.RunWorkerCompleted += Bw_RunWorkerCompleted; bw.RunWorkerAsync(); Console.ReadKey(); } private static void Bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { Console.WriteLine("Complete."); Console.WriteLine(e.Error); } private static void Bw_DoWork(object sender, DoWorkEventArgs e) { throw new NotImplementedException(); }