c# – BackgroundWorker.RunWorkCompleted – 无法重新抛出异常
发布时间:2020-12-15 21:42:12 所属栏目:百科 来源:网络整理
导读:我正在为WCF调用(使用BackgroundWorker)编写某种包装器,以便在调用正在进行时保持GUI不冻结.它主要是按预期工作,但是当WCF调用抛出异常时,我遇到了BackgroundWorker的问题.如果在DoWork中发生异常,我可以在RunWorkCompleted中检测到它,但是将其重新抛出到GUI
我正在为WCF调用(使用BackgroundWorker)编写某种包装器,以便在调用正在进行时保持GUI不冻结.它主要是按预期工作,但是当WCF调用抛出异常时,我遇到了BackgroundWorker的问题.如果在DoWork中发生异常,我可以在RunWorkCompleted中检测到它,但是将其重新抛出到GUI不起作用.我已经读了很多线程,人们提到这应该有效.
包装器的代码(注意WCF调用由抛出的异常表示): private void GetSomething(Action<IEnumerable<int>> completedAction) { BackgroundWorker b = new BackgroundWorker(); b.DoWork += (s,evt) => { throw new Exception(); evt.Result = new List<int> { 1,2,3 }; }; b.RunWorkerCompleted += (s,evt) => { if (evt.Error == null && completedAction != null) { completedAction((IEnumerable<int>)evt.Result); } else if(evt.Error != null) { throw evt.Error; } }; b.RunWorkerAsync(); } 在Windows窗体中调用代码: private void button3_Click(object sender,EventArgs e) { try { GetSomething(list => { foreach (int i in list) { listView1.Items.Add(new ListViewItem(i.ToString())); } }); } catch (Exception ex) { MessageBox.Show(ex.Message); } } 在调试时,我得到:
我究竟做错了什么?我想在Windows窗体中捕获异常. 解决方法
事件b.RunWorkerCompleted是您应该进行错误处理的地方.您可以传递一个Action< Exception>做错误处理就像
private void GetSomething(Action<IEnumerable<int>> completedAction,Action<Exception> exceptionAction) { BackgroundWorker b = new BackgroundWorker(); b.DoWork += (s,evt) => { if (evt.Error == null && completedAction != null) completedAction((IEnumerable<int>)evt.Result); else if(evt.Error != null) exceptionAction(evt.Error); }; b.RunWorkerAsync(); } 然而,这往往会变得丑陋.如果您使用.Net 4或4.5,则可以使用“任务”.任务< TResult>是为了这种情况而创建的: Task<IEnumerable<int>> GetSomething() { return Task.Factory.StartNew(() => { Thread.Sleep(2000); throw new Exception(); return (new List<int> { 1,3 }).AsEnumerable(); }); } 任务基本上是一个信号构造 > a.结果财产 在ContinueWith()中,您可以检查Task是否处于故障状态(Exception被抛出). 你可以像使用它一样 private void button3_Click(object sender,EventArgs e) { GetSomething() .ContinueWith(task => { if (task.IsCanceled) { } else if (task.IsFaulted) { var ex = task.Exception.InnerException; MessageBox.Show(ex.Message); } else if (task.IsCompleted) { var list = task.Result; foreach (int i in list) { listView1.Items.Add(new ListViewItem(i.ToString())); } } }); } 如果您使用.Net 4.5和C#5(您需要VS2012或VS2010和Async CTP),您甚至可以使用异步并等待 private async void button3_Click(object sender,EventArgs e) { try { var list = await GetSomething(); foreach (int i in list) { listView1.Items.Add(new ListViewItem(i.ToString())); } } catch (Exception ex) { MessageBox.Show(ex.Message); } } ……所有的魔力都是由编译器完成的.请注意,您可以像以前一样使用try catch. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |