Ez a cikk egy tükör gépi fordítás, kérjük, kattintson ide, hogy ugorjon az eredeti cikkre.

Nézet: 6277|Válasz: 2

[Kommunikáció] [Fordul] Egy mondat: Feladat.Eredmény zárolódik, hogyan írhatnánk másért ezt a kódot?

[Linket másol]
Közzétéve: 2022-8-7 21:11:58 | | | |
1: Háttér

1. Mesélj történeteket

Néhány nappal ezelőtt, amikor indexeltem a cikket a .NET Advanced Debugging-en a githubra, találtam egy érdekes hozzászólást, nézd meg a cikket a részletekért, a képernyőkép a következő:



Valószínűleg azt jelenti, hogy a Winform fő szálában a Task.Result futtatása holtpontot okoz, én is megnéztem a képen lévő hivatkozási linket, Stephen az abszolút főellenség, de ez a cikk főként egy nagy bekezdés betanításáról szól, és nem igazán láthatod, amit látsz, ezért a windbg nézőpontából fogom elemezni.

2: Windbg elemzés

1. Valóban holtpontba kerül?

Természetesen évek óta nem játszottam a winform-tal, és nem tudom, hogy ez így lesz-e, legalábbis a konzolon nem.

A kód nagyon egyszerű: futtatd a programot, kattints kattints, és valóban, az interfész beragadt, ami eléggé hihetetlen.

2. Keresse meg a patthelyzet okát

Ezután siess, és csatold a szélbg-et a folyamathoz, hogy kiderítsd.

1) Nézd meg a fő témát
A felület nem reagál, így természetesen a fő szál elakadt, ezért meg kell nézned, mit csinál most a fő szál. Használd a ~0s + !clrstack parancsot.

0:000> !clrstack
OS szálazonosító: 0x5a10 (0)
        Gyermek SP IP hívás oldal
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]
A stack kimenetéből a fő szál végül beragadt a Monitor.ObjWait szerveren a Task.Result alatt, ami azt jelenti, hogy még nem kapta le az utolsó jsonStringet, ami nagyon furcsa, már több perc telt el, van valami probléma a hálózattal? A hálóm 100 méteres tűzerővel telik...

2) Hová tűnt a jsonString?
Ha a jsonString a kezelt halomon található, az azt jelenti, hogy a programban van valami, ami késlelteti az eredményt, használd a !dumpheap -type String -min 8500 + !do 000001f19002fcf0 parancsot a megtekintéshez, ahogy az alábbi ábrán látható:



Az ábrán egyértelműen látható, hogy a html visszatért, mivel minden visszatért, miért nem ért még véget a Task.Result ? A következő lépés, hogy megnézzük, ki birtokolja ezt a html-t, és használod a !gcrootot.

0:000> !gcroot 000001f19002fcf0
5a10 szál:
    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 Rendszer.Eseménykezelő
            -> 000001f1800716b0 System.Windows.Forms.ApplicationContext
            -> 000001f180071780 rendszer. EventHandler
            -> 000001f18006ab38 System.Windows.Forms.Application+ThreadContext
            -> 000001f18006b140 System.Windows.Forms.Application+MarshalingControl
            -> 000001f18016c9c8 System.Collections.Queue
            -> 000001f18016ca00 Rendszer.Objektum[]
            -> 000001f18016c948 System.Windows.Forms.Control+ThreadMethodEntry
            -> 000001f18016c8b8 Rendszer.Objektum[]
            -> 000001f1800e6f80 rendszer. Akció
            -> 000001f1800e6f60 System.Runtime.CompilerServices.AsyncMethodBuilderCore+MoveNextRunner
            -> 000001f1800a77d0 WindowsFormsApp4.Form1+<GetJsonAsync>d__2
            -> 000001f1800b4e50 System.Threading.Tasks.Task'1[[System.String, mscorlib]]
            -> 000001f19002fcf0 rendszer. String

Találtam 1 egyedi gyökeret (fuss '! GCRoot -mindenki, hogy minden gyökeret lássak).
A kimeneti eredmények alapján ez a System.String végül a 5a10 szál WindowsFormsApp4.Form1-je által tárolható, és az !t segítségével ellenőrizheted, mi az 5a10 szál.

0:000> !t Zár  
       ID OSID ThreadOBJ State GC Mode GC Alloc Context Domain Count Apt Exception
   0 1 5a10 000001f1f1b01200 2026020 Preemptív 000001F1800E70E8:000001F1800E7FD0 000001f1f1ad5b90 0 STA
   2 2 712c 000001f1f1b2a270 2b20 Preemptív 00000000000000000:000000000000000 000000000 0000001f1f1ad5b90 0 MTA (Véglegesítő)
Én elmondtam, hogy az 5a10 lett a fő szál, ami elég zavaros volt, a fő szál beragadt, és a húr a fő szál által tartott, teljesen megmagyarázhatatlan.

3) Keress kitörési pontokat
Még mindig visszamegyve és nyugodtan gondolkodva ezen a referencialáncon, rájöttem, hogy itt van egy Queue: -> 000001f18016c9c8 System.Collections.Queue, van egy ötletem, hogy hibázhatom a forráskódot úgy, hogy egy megszakítási pontot helyezek a Queue-ba, és az eszköz DnSpy-t használ, csak csináld meg.



Ahogy az ábrán látható, a Queue belépéskor a 10-es szálat használják, ami azt jelenti, hogy a string jelenleg még nem tartja a fő szálat.



Az ábrából látható, hogy a folyamatos feladatot végül WindowsFormsSynchronizationContext.Post ütemezi a Control alatt lévő sorba, és a sorban lévő adatokat a UI szál hajtja végre, így a következő párbeszéd látható:

Fő szál: Feladat, testvér, mikor fejezed be a végrehajtást? Várom, hogy befejezd a jelet?

feladat:Testvér, ha nem végezsz ki, hogyan fejezhetném be?

Fő téma:Ó...

Összefoglalva: a folytatási feladat elérte a sort, amely a fő szál végrehajtására vár, és ekkor a fő szál megkábítva van, és várja, hogy a folytatási feladat befejeződjön=true legyen, a probléma itt van: hogyan lehet a folytatási feladat nem teljesíthető Complete=true? Így vannak.

Három: Hogyan törd meg

Az ok-okozat ismeretével ez a repedési módszer egyszerű, nagyjából két típusra osztva.

1. Tilos egy folytatási feladatot sorba dobni

Ennek az útnak a levágása azt jelenti, hogy hagyjuk, hogy a szál pool magától fejezze be a feladatot, így a UI szál érzékelheti, hogy a feladat befejeződött, és végül a UI szál megkaphatja a végső html-t, amely a ConfigureAwait (false) hozzáadását jelenti a várakozás után, az alábbiak szerint:



2. Blokkold le a fő szálat

Ha a fő szál nincs blokkolva, akkor a fő szál szabadon megkaphatja a végrehajtandó feladatokat a Control.Queue-ban, és a módszer nagyon egyszerű: csak add hozzá az await gombot a GetJsonAsync előtt.



Három: Összefoglaló

A következtetés az, hogy többet végezz a saját gyakorlatodból, az elméleti tudást mások kényszerítik rád, akár helyes, akár helytelen, valójában nincs mély mélyed, a gyakorlati ellenőrzés az, ami igazán hozzád tartozik, és nehéz elfelejteni, hiszen valóban megtapasztaltad, gyakoroltad és ellenőrizted.

Eredeti:A hiperlink bejelentkezés látható.





Előző:A Docker módosítja és korlátozza a konténer CPU-t, memóriát és egyéb erőforrásokat
Következő:A JS tömbök a különbség és a használat minden és néhány rész
Közzétéve: 2022-8-8 17:01:32 |
Tanulj meg...
Közzétéve: 2022-9-2 11:39:19 |
Tanulj meg egy kicsit
Lemondás:
A Code Farmer Network által közzétett összes szoftver, programozási anyag vagy cikk kizárólag tanulási és kutatási célokra szolgál; A fenti tartalmat nem szabad kereskedelmi vagy illegális célokra használni, különben a felhasználók viselik az összes következményet. Az oldalon található információk az internetről származnak, és a szerzői jogi vitáknak semmi köze ehhez az oldalhoz. A fenti tartalmat a letöltés után 24 órán belül teljesen törölni kell a számítógépéről. Ha tetszik a program, kérjük, támogassa a valódi szoftvert, vásároljon regisztrációt, és szerezzen jobb hiteles szolgáltatásokat. Ha bármilyen jogsértés történik, kérjük, vegye fel velünk a kapcsolatot e-mailben.

Mail To:help@itsvse.com