Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How to solve the problem of deadlock in Task.Result

2025-02-22 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/03 Report--

How to solve the Task.Result deadlock problem, many novices are not very clear about this, in order to help you solve this problem, the following editor will explain for you in detail, people with this need can come to learn, I hope you can gain something.

I. background

1. Tell a story

A few days ago, during the process of indexing .NET advanced debugging articles into https://github.com/ctripxchuang/dotnetfly, I found an interesting comment. The screenshot is as follows:

That is to say, executing Task.Result under the main thread of Winform will cause deadlock. I have also seen the reference link in the picture. Stephen is the absolute boss, but this article mainly inculcates large sections of text about the cause of deadlock. It doesn't really make you believe what you see, so I'll analyze it from the perspective of windbg.

2. Windbg analysis

1. Will it really be deadlocked?

Look at the article, screenshots really seem to deadlock, of course, I haven't played winform for many years, and I don't know if it will, at least not in Console, so let's test the code first.

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 GetJsonAsync (string uri) {using (var client = new HttpClient ()) {var jsonString = await client.GetStringAsync (uri); return jsonString;}

The code is very simple, run the program, click click, sure enough, the interface is stuck, a little incredible.

two。 Looking for the cause of the deadlock

Next, hurry up to add windbg to the process to find out.

1) View the main thread

The interface is unresponsive, and naturally the main thread is stuck, so it is urgent to see what the main thread is doing at this time. Use the command ~ 0s +! clrstack.

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. Thread. 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]

From the stack output, the main thread is finally stuck on the Monitor.ObjWait under Task.Result, that is to say, it has not yet got the final jsonString, which is very strange, it has been several minutes, is there something wrong with the network? My net is full of 100m firepower. ?

2) where is jsonString?

A good way to determine whether it is a network problem is to directly violently search the managed heap. If jsonString is found on the managed heap, it means that there is something in the program that keeps the Result from ending. Use the command! dumpheap-type String-min 8500 +! do 000001f19002fcf0 to check, as shown in the following figure:

You can clearly see from the picture that html is back, since it's all back, why haven't you let Task.Result end yet? The next step is to see who owns the html and use! gcroot.

0VOL000 >! 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+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).

From the output, the System.String is finally held by the WindowsFormsApp4.Form1 of the 5a10 thread, and you can use! t to verify what the 5a10 is.

T Lock ID OSID ThreadOBJ State GC Mode GC Alloc Context Domain Count Apt Exception 01 5a10 000001f1f1b01200 2026020 Preemptive 000001F1800E70E8:000001F1800E7FD0 000001f1f1ad5b90 0 STA 22 712c 000001f1f1b2a270 2b220 Preemptive 0000000000000000000000000000 000001f1f1ad5b90 0 MTA (Finalizer)

When I go, 5a10 turns out to be the main thread, which is really a little confusing. The main thread is stuck and the string is held by the main thread, which is completely inexplicable.

3) looking for a breakthrough.

Or go back to think calmly about this quote chain, I found that there is a Queue:- > 000001f18016c9c8 System.Collections.Queue, there is an idea, I can enter the Queue where the next breakpoint to debug the source code, tools with DnSpy, say dry.

As you can see from the figure, thread 10 is currently used when entering Queue, that is to say, the string is not held by the main thread at this time. If you analyze the call stack carefully, I think you should figure it out. Anyway, I have this picture in my head after reading it.

You can see from the figure that the continuous Task is finally dispatched by WindowsFormsSynchronizationContext.Post to the Queue under Control, and the data in this Queue needs to be executed by the UI thread, so there is the following dialogue:

Main thread: little brother task, when will you finish your execution? I'm waiting for your signal.

Task: brother, I'm already at your house. When are you coming to pick me up?

All in all: task needs the main thread to execute it, but the main thread is foolishly waiting for the complete state of task, so the extended task will never be executed, which is a very embarrassing scene. Do you understand?

Third, the method of cracking

Knowing the causes and consequences, the method of cracking is simple, generally divided into two kinds.

1. It is forbidden to throw continuation task into Queue.

To cut off this path, the implication is to let the thread pool end the task itself, so that the UI thread can perceive that the task has been completed, and eventually the UI thread can obtain the final html by adding ConfigureAwait (false) after the await, as shown below:

two。 Do not block the main thread

If the main thread is not blocked, then the main thread is free to get the tasks that need to be executed in Control.Queue, and the correction is very simple, just add await before the GetJsonAsync.

Is it helpful for you to read the above content? If you want to know more about the relevant knowledge or read more related articles, please follow the industry information channel, thank you for your support.

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report