C#4.0的并行库TPL,即Task(一)http://www.skcircle.com/?id=1793
C#4.0的并行库TPL,即Task(二) http://www.skcircle.com/?id=1798
C#4.0的并行库TPL,即Task(三) http://www.skcircle.com/?id=1808
C#4.0的并行库TPL,即Task(四) http://www.skcircle.com/?id=1815
C#4.0的并行库TPL,即Task(五) http://www.skcircle.com/?id=1816
C#4.0的并行库TPL,即Task(六) http://www.skcircle.com/?id=1831
勇哥继续这个话题,从这一篇开始,记录使用TPL实际开发时遇到的一些问题。
(一)未通过等待任务或访问任务的 Exception 属性观察到任务的异常。因此,终结器线程重新引发了未观察到的异常。
由于注册了事件UnobservedTaskException, 因此出现上面的异常时,被捕获到了。
TaskScheduler的UnobservedTaskException事件原型如下:
我搜索了一网上,有人遇到这个问题。
---------------引用如下:----------------------------------------------
这些是我的任务。 我应该如何修改它们以防止此错误。 我检查了其他类似的线程,但我正在使用等待并继续。 那怎么会发生这个错误呢?
通过等待任务或访问其Exception属性,未观察到任务的异常。 结果,终结器线程重新抛出了未观察到的异常。
var CrawlPage = Task.Factory.StartNew(() => { return crawlPage(srNewCrawledUrl, srNewCrawledPageId, srMainSiteId); }); var GetLinks = CrawlPage.ContinueWith(resultTask => { if (CrawlPage.Result == null) { return null; } else { return ReturnLinks(CrawlPage.Result, srNewCrawledUrl, srNewCrawledPageId, srMainSiteId); } }); var InsertMainLinks = GetLinks.ContinueWith(resultTask => { if (GetLinks.Result == null) { } else { instertLinksDatabase(srMainSiteURL, srMainSiteId, GetLinks.Result, srNewCrawledPageId, irCrawlDepth.ToString()); } }); InsertMainLinks.Wait(); InsertMainLinks.Dispose();
你没有处理任何异常。
改变这一行:
InsertMainLinks.Wait();
改为:
try { InsertMainLinks.Wait(); } catch (AggregateException ae) { /* Do what you will */ }
通常:为了防止终结器重新抛出源自工作线程的任何未处理的异常,您可以:
等待线程并捕获System.AggregateException,或者只读取异常属性。
例如:
Task.Factory.StartNew((s) => { throw new Exception("ooga booga"); }, TaskCreationOptions.None).ContinueWith((Task previous) => { var e=previous.Exception; // Do what you will with non-null exception });
或者为:
Task.Factory.StartNew((s) => { throw new Exception("ooga booga"); }, TaskCreationOptions.None).ContinueWith((Task previous) => { try { previous.Wait(); } catch (System.AggregateException ae) { // Do what you will } });
---------------引用结束----------------------------------------------
上面问者代码中的问题很明显,只是没有处理可能的异常,因此答者建议使用后续任务或者把Wait用try来捕捉异常。
这样就不会弹出这种异常了。
然尔勇哥的代码显示不是上面说的这么简单出错原因:
如下图所示,后续任务已经处理了异常,并且Wait也加了try捕捉 AggregateException异常。
另外,还观察了一下TryExecuteTask看是不是false出错,结果也不是。
结果还是弹出未处理的异常报错信息。
这个问题困惑了许久,后来发现是异步互锁造成的问题。
勇哥在异步方法中,加入配置异步上下文的方法ConfigureAwait(false) 就OK了。
有关异步互锁的话题本篇就不详细列举了,详细见下面的贴子:
c# 非async方法调用async方法 http://www.skcircle.com/?id=1844
C#中Async/Await 异步编程中的最佳做法 http://www.skcircle.com/?id=1843
C# 异步和等待,async/await http://www.skcircle.com/?id=1842
C# 微软async开发者团队关于async/await常见问题的解答 http://www.skcircle.com/?id=1841
C# 不要阻塞异步代码,即异步代码死锁的最佳解决方案 http://www.skcircle.com/?id=1840
---------------------
作者:hackpig
来源:www.skcircle.com
版权声明:本文为博主原创文章,转载请附上博文链接!

