多線程和非同步編程示例和實踐-踩過的坑
上兩篇文章,主要介紹了Thread、ThreadPool和TPL
本文中,分享兩則我們在做多線程和非同步編程中實際踩過的坑,實際生產環境遇到的問題,以及解決辦法。
1. HttpClient
業務場景:使用HttpClient實現第三方業務推送,當第三方的Http伺服器不通、或者返回很慢時
- 線程數暴漲
- Asp.NetAsp.Net MVC場景下,並發多線程導致的線程阻塞:HttpClient.PostAysnc/GetAsync.Result
第一種線程數暴漲的問題,很容易理解,線程執行的慢,線程創建的速度快,一直在執行,導致線程不斷創建線程、線程數不斷暴漲。
根本原因是HttpClient的超時時間配置的太長,這點存於業務設計的問題,理論上簡單請求3s沒響應就該超時了,複雜長時間請求使用非同步任務(我們的消息應用中心)處理。
第二種,Asp.Net或者Asp.Net MVC場景下,使用HttpClient,同時GetAsync.Result,非同步變同步,這就會出現請求Hang住,線程死鎖、請求沒響應。
根本原因是Http非同步請求的上下文的互相等待導致的。詳細分析可以參考下面的link:
有什麼好的解決方案嗎?
- HttpWebRequest代替HttpClient實現各類Http請求,這個類雖然是.net 2.0下的,但是功能的確很強大,應用一般的Http請求沒啥問題!
- 使用HttpWebRequest實現同步Get、Post請求,避免在Asp.Net場景下使用HttpClient.PostAsync/GetAsync.Result(非同步變同步)帶來的線程死鎖,因為Asp.Net機制下Http非同步請求的上下文的互相等待導致的。
- 合理設置Http請求的超時時間,超時即返回,防止線程數暴漲
- 對於第三方伺服器的通信,建議在內存中維護一個聯通性狀態字典,每隔一段時間更新一次,如果不通,直接就不發起Http請求了,這個策略更像是設計上的優化,但是效果很好!
上兩個示例代碼:
如果非用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
※EF Core學習Code First
※cordova 插件開發
TAG:達人科技 |
※核桃編程:讓孩子學習編程的進步清晰可見
※程序員的編程能力與編程年齡
※編程測試,程序員過不去的坎?
※編程進階之路:用簡單的面向對象編程提升深度學習原型
※編程小白和Ta的進階之旅
※發生在編程過程中的五件趣事
※最硬核的遊戲,完整還原編程的步驟,不會編程連任務都看不懂
※多地編程協作的必備技——遠程結對編程
※AI時代學什麼穩賺不賠?編程,編程,編程
※數控行業現狀與前景的探討,一個編程工程師的肺腑之言
※傲夢編程推出「少兒編程萬人普及計劃」,演繹編程魅力
※學習編程,真正的攔路虎是什麼?
※小程序對實體店的好處,怎麼賺錢?介紹一個免編程小程序製作平台
※一個女程序員的編程之路
※異型螺紋編程實例,擴展你的思路
※編程向未來,科技強國夢——雲和數據即將推出「少兒編程」課程!
※從「少兒編程」到編程
※編程前的準備
※在真實工作中的編程是怎麼樣的,與學校里有什麼不同?
※谷歌軟體工程師分享編程經驗:有效的流程很關鍵