多线程和异步编程示例和实践-踩过的坑
上两篇文章,主要介绍了Thread、ThreadPool和TPL 多线程异步编程示例和实践-Thread和ThreadPool 多线程异步编程示例和实践-Task 本文中,分享两则我们在做多线程和异步编程中实际踩过的坑,实际生产环境遇到的问题,以及解决办法。 1. HttpClient 业务场景:使用HttpClient实现第三方业务推送,当第三方的Http服务器不通、或者返回很慢时
第一种线程数暴涨的问题,很容易理解,线程执行的慢,线程创建的速度快,一直在执行,导致线程不断创建线程、线程数不断暴涨。 根本原因是HttpClient的超时时间配置的太长,这点存于业务设计的问题,理论上简单请求3s没响应就该超时了,复杂长时间请求使用异步任务(我们的消息应用中心)处理。 第二种,Asp.Net或者Asp.Net MVC场景下,使用HttpClient,同时GetAsync.Result,异步变同步,这就会出现请求Hang住,线程死锁、请求没响应。 根本原因是Http异步请求的上下文的互相等待导致的。详细分析可以参考下面的link: http://blog.stephencleary.com/2012/07/dont-block-on-async-code.html 有什么好的解决方案吗?
上两个示例代码: 如果非用HttpClient不可,也是有招的: 很简单,从WebApi,或者Controller这一层全部异步化。前后全部异步。同时, 设置:ConfigureAwait(false) 2. Winform、Console或者Windows服务下,前台线程异常导致的进程退出 这个问题是很头疼的,主要是在提供的服务容器运行的插件代码中,使用了Thread,默认是前台线程,未正确处理异常,线程异常后,导致主进程退出!!! 业务场景:Windows 服务版本下的消息应用中心,个推使用New Thread推送消息,线程未处理异常,异常后导致Windows Service异常关闭! 结果很头大,就是整个消息应用中心进程退出了,所有消息处理业务全部受影响! 根本原因:通过New Thread方式创建的线程,系统默认都是前台线程(IsBack),前台线程异常如果未处理,会导致应用程序退出,即使注册了AppDomain.CurrentDomain.UnhandledException事件处理,应用程序依然会挂掉。 解决方案:在线程内部合理处理异常:记日志、返回值处理,但是不能throw! 补充:这里引出了一个重要的知识点:前台线程和后台线程 两者的区别就是:
那么,Thread、线程池的线程、Task都各自属于哪一类线程? 使用Thread建立的线程默认情况下是前台线程,即线程属性IsBackground=false. 属于托管线程池的线程(即其 IsThreadPoolThread 属性为 true 的线程)是后台线程 Task都是后台线程:Task需要在其运行过程中至少有一个前台线程在跑,否则会直接退出. ? 周国庆 2017/6/16 ? (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
- asp.net – 仅在本地主机上使用Fiddler
- asp.net-mvc-3 – 如何使用ASP.NET MVC 3“Razor
- asp.net – 如何追踪过期的WIF fedauth cookies?
- asp.net – 为什么在调用Application_Error()时R
- asp.net-core – MVC 6 Web Api:解析201上的位置
- asp.net – 使文本框不可编辑
- 给 EF Core 查询增加 With NoLock
- asp.net-mvc-3 – 使用EditorFor/TextBoxFor/Tex
- 在ASP.Net MVC的视图中使用Silverlight – 一个坏
- asp.net-mvc – 使用ASP.NET身份重置密码时的令牌