欧美一区二区三区老妇人-欧美做爰猛烈大尺度电-99久久夜色精品国产亚洲a-亚洲福利视频一区二区

如何解決Task.Result就死鎖的問題

如何解決Task.Result就死鎖的問題,很多新手對此不是很清楚,為了幫助大家解決這個難題,下面小編將為大家詳細講解,有這方面需求的人可以來學習下,希望你能有所收獲。

我們提供的服務有:網(wǎng)站設計、成都做網(wǎng)站、微信公眾號開發(fā)、網(wǎng)站優(yōu)化、網(wǎng)站認證、神木ssl等。為上1000+企事業(yè)單位解決了網(wǎng)站和推廣的問題。提供周到的售前咨詢和貼心的售后服務,是有科學管理、有技術的神木網(wǎng)站制作公司

一、背景

1. 講故事

前些天把 .NET 高級調試 方面的文章索引到 https://github.com/ctripxchuang/dotnetfly  的過程中,發(fā)現(xiàn)了一個有意思的評論,截圖如下:

如何解決Task.Result就死鎖的問題

大概就是說在 Winform 的主線程下執(zhí)行 Task.Result 會造成死鎖,我也看了圖中的參考鏈接, Stephen  是絕對的大佬,不過這篇文章對死鎖的成因主要還是大段的文字灌輸,沒有真的讓你眼見為實,那這篇我就從 windbg 的角度來給它剖析下。

二、windbg 分析

1. 真的會死鎖嗎?

看文章看截圖貌似真的會死鎖,當然我多年不玩 winform 了,也搞不清楚到底會不會,至少在 Console 中是不會的,得,先上一段測試代碼。

public partial class Form1 : Form     {         public Form1()         {             InitializeComponent();         }          private void button1_Click(object sender, EventArgs e)         {             var jsonTask = GetJsonAsync("http://cnblogs.com").Result;             textBox1.Text = jsonTask;         }          public async static Task<string> GetJsonAsync(string uri)         {             using (var client = new HttpClient())             {                 var jsonString = await client.GetStringAsync(uri);                  return jsonString;             }         }     }

代碼非常簡單,把程序跑起來,點一下 click,果然界面卡住了,有點不可思議。

2. 尋找死鎖原因

接下來趕緊祭出 windbg 附加到進程上一探究竟吧。

1) 查看主線程

界面無響應了,自然是主線程卡住了,所以急需看一下此時的主線程在干嘛?用命令 ~0s + !clrstack 即可。

0:000> !clrstack  OS Thread Id: 0x5a10 (0)         Child SP               IP Call Site 0000004d10dfde00 00007ffb889a10e4 [GCFrame: 0000004d10dfde00]  0000004d10dfdf28 00007ffb889a10e4 [HelperMethodFrame_1OBJ: 0000004d10dfdf28] System.Threading.Monitor.ObjWait(Boolean, Int32, System.Object) 0000004d10dfe040 00007ffb66920d64 System.Threading.ManualResetEventSlim.Wait(Int32, System.Threading.CancellationToken) 0000004d10dfe0d0 00007ffb6691b4bb System.Threading.Tasks.Task.SpinThenBlockingWait(Int32, System.Threading.CancellationToken) 0000004d10dfe140 00007ffb672601d1 System.Threading.Tasks.Task.InternalWait(Int32, System.Threading.CancellationToken) 0000004d10dfe210 00007ffb6725cfa7 System.Threading.Tasks.Task`1[[System.__Canon, mscorlib]].GetResultCore(Boolean) 0000004d10dfe250 00007ffb18172a1b WindowsFormsApp4.Form1.button1_Click(System.Object, System.EventArgs) [E:\net5\ConsoleApp1\WindowsFormsApp4\Form1.cs @ 26] 0000004d10dfe2b0 00007ffb3a024747 System.Windows.Forms.Control.OnClick(System.EventArgs) 0000004d10dfe2f0 00007ffb3a027b83 System.Windows.Forms.Button.OnClick(System.EventArgs) 0000004d10dfe340 00007ffb3a837231 System.Windows.Forms.Button.OnMouseUp(System.Windows.Forms.MouseEventArgs) 0000004d10dfe400 00007ffb3a7e097d System.Windows.Forms.Control.WmMouseUp(System.Windows.Forms.Message ByRef, System.Windows.Forms.MouseButtons, Int32) 0000004d10dfe480 00007ffb3a0311cc System.Windows.Forms.Control.WndProc(System.Windows.Forms.Message ByRef) 0000004d10dfe540 00007ffb3a0b0c97 System.Windows.Forms.ButtonBase.WndProc(System.Windows.Forms.Message ByRef) 0000004d10dfe5c0 00007ffb3a0b0be5 System.Windows.Forms.Button.WndProc(System.Windows.Forms.Message ByRef) 0000004d10dfe5f0 00007ffb3a030082 System.Windows.Forms.NativeWindow.Callback(IntPtr, Int32, IntPtr, IntPtr) 0000004d10dfe690 00007ffb3a765a02 DomainBoundILStubClass.IL_STUB_ReversePInvoke(Int64, Int32, Int64, Int64) 0000004d10dfe9d0 00007ffb776d221e [InlinedCallFrame: 0000004d10dfe9d0] System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG ByRef) 0000004d10dfe9d0 00007ffb3a0b9489 [InlinedCallFrame: 0000004d10dfe9d0] System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG ByRef) 0000004d10dfe9a0 00007ffb3a0b9489 DomainBoundILStubClass.IL_STUB_PInvoke(MSG ByRef) 0000004d10dfea60 00007ffb3a046661 System.Windows.Forms.Application+ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(IntPtr, Int32, Int32) 0000004d10dfeb50 00007ffb3a045fc7 System.Windows.Forms.Application+ThreadContext.RunMessageLoopInner(Int32, System.Windows.Forms.ApplicationContext) 0000004d10dfebf0 00007ffb3a045dc2 System.Windows.Forms.Application+ThreadContext.RunMessageLoop(Int32, System.Windows.Forms.ApplicationContext) 0000004d10dfec50 00007ffb181708e2 WindowsFormsApp4.Program.Main() [E:\net5\ConsoleApp1\WindowsFormsApp4\Program.cs @ 19] 0000004d10dfee78 00007ffb776d6923 [GCFrame: 0000004d10dfee78]

從堆棧輸出看,主線程最后是卡在 Task.Result 下的 Monitor.ObjWait 上,也就是說它還沒有取到最后的  jsonString,這就很奇怪了,都好幾分鐘了,難道網(wǎng)絡出問題啦 ? 我這網(wǎng)可是100M火力全開。。。??????

2) jsonString 哪去了?

判斷是不是網(wǎng)絡的問題,有一個好辦法,那就是直接暴力搜索托管堆,如果在托管堆上發(fā)現(xiàn)了 jsonString,那就說明是程序上的某些地方讓 Result  遲遲得不到結束,用命令 !dumpheap -type String -min 8500 + !do 000001f19002fcf0  查看即可,如下圖所示:

如何解決Task.Result就死鎖的問題

從圖中可以清晰的看出 html 回來了,既然都回來了,為啥還沒讓 Task.Result 結束呢?下一步就是看一看這個 html 被誰持有,使用  !gcroot 即可。

0:000> !gcroot 000001f19002fcf0 Thread 5a10:     0000004d10dfe250 00007ffb18172a1b WindowsFormsApp4.Form1.button1_Click(System.Object, System.EventArgs) [E:\net5\ConsoleApp1\WindowsFormsApp4\Form1.cs @ 26]         rbp+10: 0000004d10dfe2b0             ->  000001f180007f78 WindowsFormsApp4.Form1             ->  000001f180070d68 System.ComponentModel.EventHandlerList             ->  000001f180071718 System.ComponentModel.EventHandlerList+ListEntry             ->  000001f1800716d8 System.EventHandler             ->  000001f1800716b0 System.Windows.Forms.ApplicationContext             ->  000001f180071780 System.EventHandler             ->  000001f18006ab38 System.Windows.Forms.Application+ThreadContext             ->  000001f18006b140 System.Windows.Forms.Application+MarshalingControl             ->  000001f18016c9c8 System.Collections.Queue             ->  000001f18016ca00 System.Object[]             ->  000001f18016c948 System.Windows.Forms.Control+ThreadMethodEntry             ->  000001f18016c8b8 System.Object[]             ->  000001f1800e6f80 System.Action             ->  000001f1800e6f60 System.Runtime.CompilerServices.AsyncMethodBuilderCore+MoveNextRunner             ->  000001f1800a77d0 WindowsFormsApp4.Form1+<GetJsonAsync>d__2             ->  000001f1800b4e50 System.Threading.Tasks.Task`1[[System.String, mscorlib]]             ->  000001f19002fcf0 System.String  Found 1 unique roots (run '!GCRoot -all' to see all roots).

從輸出結果看,這個 System.String 最后被 5a10 線程的 WindowsFormsApp4.Form1 持有,可以用 !t 驗證一下  5a10 到底是什么線程。

0:000> !t                                                                                                        Lock          ID OSID ThreadOBJ           State GC Mode     GC Alloc Context                  Domain           Count Apt Exception    0    1 5a10 000001f1f1b01200  2026020 Preemptive  000001F1800E70E8:000001F1800E7FD0 000001f1f1ad5b90 0     STA     2    2 712c 000001f1f1b2a270    2b220 Preemptive  0000000000000000:0000000000000000 000001f1f1ad5b90 0     MTA (Finalizer)

我去,5a10 竟然是主線程,真的有點混亂,主線程被卡死,string 又被主線程持有,完全是莫名其妙。

3) 尋找突破點

還是回過頭下冷靜思考下這條 引用鏈,我發(fā)現(xiàn)這里有一個 Queue:-> 000001f18016c9c8  System.Collections.Queue,有思路了,我可以在入 Queue 的地方下個 斷點 來調試下源代碼,工具用 DNSpy, 說干就干。

如何解決Task.Result就死鎖的問題

從圖中可以看到,當前入Queue時,用的是線程 10,也就是說此時 string  還沒被主線程持有,再仔細分析下這個調用棧,我想你應該就搞清楚了,反正我看完之后腦子中就有了這張圖。

如何解決Task.Result就死鎖的問題

從圖中可以發(fā)現(xiàn),延續(xù)的 Task 最后被 WindowsFormsSynchronizationContext.Post 調度到了 Control 下的  Queue 中,而這 Queue 中的數(shù)據(jù)需要 UI線程 去執(zhí)行,所以就有了下面的對話:

主線程: task小弟,你什么時候執(zhí)行完呀,我在等你信號呢?

task: 老哥,我已在你家啦,你什么時候過來接我呀?

總而言之:task需要主線程來執(zhí)行它,主線程卻在傻傻的等待 task 的 complete  狀態(tài),所以延續(xù)的task永遠得不到執(zhí)行,這就出現(xiàn)了很尷尬的場面,不知道你明白了嗎? ??????

三、破解之法

知道了前因后果,這破解之法就簡單了,大體上分兩種。

1. 禁止將 延續(xù)task 丟到 Queue 中

要切斷這條路,言外之意就是讓線程池自己結束這個 task,這樣 UI線程 就能感知到這個task已完成,最終 UI線程 就能獲取最后的  html,做法就是在 await 后加上 ConfigureAwait(false) , 參考如下:

如何解決Task.Result就死鎖的問題

2. 禁止阻塞主線程

如果不阻塞主線程,那么主線程就可以自由的在 Control.Queue 中獲取需要執(zhí)行的任務,改法也很簡單,只需要在 GetJsonAsync 前加上  await 即可。

如何解決Task.Result就死鎖的問題

看完上述內容是否對您有幫助呢?如果還想對相關知識有進一步的了解或閱讀更多相關文章,請關注創(chuàng)新互聯(lián)行業(yè)資訊頻道,感謝您對創(chuàng)新互聯(lián)的支持。

本文題目:如何解決Task.Result就死鎖的問題
瀏覽地址:http://chinadenli.net/article30/iegdso.html

成都網(wǎng)站建設公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站改版、商城網(wǎng)站品牌網(wǎng)站制作、外貿網(wǎng)站建設、、網(wǎng)站設計公司

廣告

聲明:本網(wǎng)站發(fā)布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經(jīng)允許不得轉載,或轉載時需注明來源: 創(chuàng)新互聯(lián)

小程序開發(fā)
日韩精品一级片免费看| 午夜精品黄片在线播放| 亚洲男人的天堂久久a| 欧美成人免费一级特黄| 日韩欧美一区二区黄色 | 日韩精品一区二区一牛| 亚洲日本中文字幕视频在线观看 | 国产又色又粗又黄又爽| 日韩精品综合福利在线观看| 日本少妇中文字幕不卡视频| 伊人网免费在线观看高清版| 午夜精品麻豆视频91| 狠狠亚洲丁香综合久久| 成年人免费看国产视频| 五月情婷婷综合激情综合狠狠 | 色婷婷视频国产一区视频| 免费在线播放一区二区| 一区二区三区18禁看| 亚洲欧美国产中文色妇| 欧美一区二区日韩一区二区| 亚洲国产综合久久天堂| 五月婷婷亚洲综合一区| 玩弄人妻少妇一区二区桃花| 精品欧美日韩一二三区 | 亚洲国产性生活高潮免费视频| 国产伦精品一一区二区三区高清版 | 午夜福利直播在线视频| 午夜福利视频六七十路熟女| 久久精品国产在热亚洲| 国产亚洲精品久久99| 亚洲一区二区三区在线免费| 欧美人禽色视频免费看| 色婷婷丁香激情五月天| 丰满人妻熟妇乱又伦精另类视频| 一区二区三区亚洲天堂| 东京干男人都知道的天堂| 中文字幕免费观看亚洲视频| 国产精品超碰在线观看| 日韩精品毛片视频免费看| 在线中文字幕亚洲欧美一区| 五月婷婷缴情七月丁香|