C#4.0的并行库TPL,即Task(六)

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, 因此出现上面的异常时,被捕获到了。


image.png

image.png


TaskScheduler的UnobservedTaskException事件原型如下:

image.png


我搜索了一网上,有人遇到这个问题。

---------------引用如下:----------------------------------------------


这些是我的任务。 我应该如何修改它们以防止此错误。 我检查了其他类似的线程,但我正在使用等待并继续。 那怎么会发生这个错误呢?

通过等待任务或访问其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出错,结果也不是。

结果还是弹出未处理的异常报错信息。


image.png


这个问题困惑了许久,后来发现是异步互锁造成的问题。

勇哥在异步方法中,加入配置异步上下文的方法ConfigureAwait(false) 就OK了。

image.png



有关异步互锁的话题本篇就不详细列举了,详细见下面的贴子:



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

版权声明:本文为博主原创文章,转载请附上博文链接!


本文出自勇哥的网站《少有人走的路》wwww.skcircle.com,转载请注明出处!讨论可扫码加群:

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

会员中心
搜索
«    2024年5月    »
12345
6789101112
13141516171819
20212223242526
2728293031
网站分类
标签列表
最新留言
    热门文章 | 热评文章 | 随机文章
文章归档
友情链接
  • 订阅本站的 RSS 2.0 新闻聚合
  • 扫描加本站机器视觉QQ群,验证答案为:halcon勇哥的机器视觉
  • 点击查阅微信群二维码
  • 扫描加勇哥的非标自动化群,验证答案:C#/C++/VB勇哥的非标自动化群
  • 扫描加站长微信:站长微信:abc496103864
  • 扫描加站长QQ:
  • 扫描赞赏本站:
  • 留言板:

Powered By Z-BlogPHP 1.7.2

Copyright Your skcircle.com Rights Reserved.

鄂ICP备18008319号


站长QQ:496103864 微信:abc496103864