Tämä artikkeli on konekäännöksen peiliartikkeli, klikkaa tästä siirtyäksesi alkuperäiseen artikkeliin.

Näkymä: 6277|Vastaus: 2

[Viestintä] [Käänny] Lause Tehtävä. Tulos lukitaan, miten muuten kirjoittaisin tämän koodin?

[Kopioi linkki]
Julkaistu 2022-8-7 21:11:58 | | | |
1: Tausta

1. Kerro tarinoita

Muutama päivä sitten, kun indeksoin artikkelin .NET Advanced Debuggingissa githubiin, löysin mielenkiintoisen kommentin, katso artikkeli yksityiskohtia varten, kuvakaappaus on seuraava:



Se tarkoittaa todennäköisesti, että Task.Resultin suorittaminen Winformin pääketjussa aiheuttaa pattitilanteen. Katsoin myös kuvassa olevaa viitelinkkiä, Stephen on ehdoton pomo, mutta tämä artikkeli käsittelee pääasiassa pitkän kappaleen aivopesua, eikä se anna sinun nähdä sitä, mitä näet, joten analysoin sitä windbg:n näkökulmasta.

2: Tuulenbg-analyysi

1. Onko se todella jumissa?

Tietenkään en ole pelannut winformia moniin vuosiin, enkä tiedä, toimiiko se, ainakaan konsolilla.

Koodi on hyvin yksinkertaista: käynnistä ohjelma, klikkaa klik, ja totta kai, käyttöliittymä on jumissa, mikä on aika uskomatonta.

2. Etsi pattitilanteen syy

Seuraavaksi kiirehdi ja kiinnitä windbg prosessiin selvittääksesi asian.

1) Katso pääteemaa
Käyttöliittymä ei reagoi, joten luonnollisesti pääsäie jumittuu, joten sinun täytyy katsoa, mitä pääsäie tekee tällä hetkellä. Käytä komentoa ~0s + !clrstack.

0:000> !clrstack
Käyttöjärjestelmän säie-ID: 0x5a10 (0)
        Lapsi SP IP Call -sivusto
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]
Pinon ulostulosteesta pääsäie on vihdoin jumissa Monitor.ObjWaitissa Task.Resultin alla, mikä tarkoittaa, ettei viimeistä jsonStringiä ole vielä hakettu, mikä on hyvin outoa, siitä on jo useita minuutteja, onko verkossa ongelma? Verkkoni on 100 metriä täynnä tulivoimaa...

2) Minne jsonString katosi?
Jos jsonString löytyy hallitusta heapista, se tarkoittaa, että ohjelmassa on jotain, joka aiheuttaa tuloksen viiveen, käytä komentoa !dumpheap -type String -min 8500 + !do 000001f19002fcf0 nähdäksesi, kuten alla olevassa kuvassa näkyy:



Kuvasta näkyy selvästi, että html on palannut, kun kaikki on palannut, miksi Task.Result ei ole vielä päättynyt? Seuraava vaihe on selvittää, kenellä on tämä html ja käyttää !gcrootia.

0:000> !gcroot 000001f19002fcf0
Ketju 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 Järjestelmä. Toiminta
            -> 000001f1800e6f60 System.Runtime.CompilerServices.AsyncMethodBuilderCore+MoveNextRunner
            -> 000001f1800a77d0 WindowsFormsApp4.Form1+<GetJsonAsync>d__2
            -> 000001f1800b4e50 System.Threading.Tasks.Task'1[[System.String, mscorlib]]
            -> 000001f19002fcf0 System.String

Löysin yhden ainutlaatuisen juuren (juokse! GCRoot -kaikki' nähdäkseni kaikki juuret).
Tulosten perusteella tämä System.String on lopulta WindowsFormsApp4.Form1:ssä 5a10-säikeessä, ja voit käyttää !t:tä tarkistaaksesi, mikä säie 5a10 on.

0:000> !t Lukko  
       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 2b20 Preemptive 00000000000000000:00000000000000000 00000000 000001f1f1ad5b90 0 MTA (Viimeistelijä)
Sanoin, että 5a10 osoittautui päälangaksi, se oli todella sekavaa, päälanka oli jumissa ja lanka oli kiinni päälangassa, täysin selittämätöntä.

3) Etsi läpimurtopisteitä
Palatessani edelleen rauhallisesti tähän viiteketjuun, huomasin, että tässä on jono: -> 000001f18016c9c8 System.Collections.Queue, minulla on idea, voin debugata lähdekoodin asettamalla breakpointin jonoon, ja työkalu käyttää DnSpyä, tee se vain.



Kuten kuvasta näkyy, jonossa käytetään säiettä 10, mikä tarkoittaa, että merkkijonoa ei vielä pidetä pääsäikeessä tällä hetkellä.



Kaaviosta näkyy, että jatkuva tehtävä ajetaan lopulta WindowsFormsSynchronizationContext.Post:n toimesta Control-jonoon, ja tämän jonon data täytyy suorittaa käyttöliittymäsäikeessä, joten seuraava dialogi on esitetty:

Pääjuoni: tehtävä veli, milloin saat sen valmiiksi? Odotan, että saat signaalin valmiiksi?

tehtävä:Veli, jos et teloita minua, miten voisin saada sen päätökseen?

Pääaihe:OH...

Yhteenvetona: jatkotehtävä on saapunut jonoon, joka odottaa pääsäikeen suoritusta, ja tällä hetkellä pääsäie on tainnutettu ja odottanut jatkotehtävän valmistumista=true, ongelma on tässä: miten jatkotehtävää ei voi suorittaa Complete=true? Joten he ovat tällaisia.

Kolme: Kuinka ratkaista se

Syy-seuraussuhteet tietäen tämä murtamismenetelmä on yksinkertainen, jaettu karkeasti kahteen tyyppiin.

1. On kiellettyä pudottaa jatkotehtävää jonoon

Tämän polun katkaisemiseksi tarkoitetaan, että säiepooli voi lopettaa tehtävän itsekseen, jolloin käyttöliittymäsäie voi havaita, että tehtävä on suoritettu, ja lopuksi käyttöliittymäsäie voi saada viimeisen html:n, joka on lisätä ConfigureAwait(false) odotuksen jälkeen, seuraavasti:



2. Estä päälanka

Jos pääsäie ei ole estetty, pääsäie voi vapaasti hakea tehtävät, jotka täytyy suorittaa Control.Queuessa, ja menetelmä on hyvin yksinkertainen: lisää vain odotus ennen GetJsonAsynciä.



Kolme: Yhteenveto

Johtopäätös on tehdä enemmän omaa käytännön harjoitustasi, teoreettinen tieto istutetaan sinuun väkisin muiden toimesta, oli se sitten oikein tai väärin, itse asiassa sinulla ei ole pohjaa sydämessäsi, käytännöllinen varmennus on se, mikä todella kuuluu sinulle, ja on vaikea unohtaa, että olet todella kokenut, harjoitellut ja varmistanut.

Alkuperäinen:Hyperlinkin kirjautuminen on näkyvissä.





Edellinen:Docker muokkaa ja rajoittaa konttiprosessoria, muistia ja muita resursseja
Seuraava:JS-taulukot ovat ero ja käyttö jokaisessa ja jossain
Julkaistu 2022-8-8 klo 17:01:32 |
Opettele oppimaan...
Julkaistu 2022-9-2 klo 11:39:19 |
Opiskele vähän
Vastuuvapauslauseke:
Kaikki Code Farmer Networkin julkaisemat ohjelmistot, ohjelmamateriaalit tai artikkelit ovat tarkoitettu vain oppimis- ja tutkimustarkoituksiin; Yllä mainittua sisältöä ei saa käyttää kaupallisiin tai laittomiin tarkoituksiin, muuten käyttäjät joutuvat kantamaan kaikki seuraukset. Tämän sivuston tiedot ovat peräisin internetistä, eikä tekijänoikeuskiistat liity tähän sivustoon. Sinun tulee poistaa yllä oleva sisältö kokonaan tietokoneeltasi 24 tunnin kuluessa lataamisesta. Jos pidät ohjelmasta, tue aitoa ohjelmistoa, osta rekisteröityminen ja hanki parempia aitoja palveluita. Jos rikkomuksia ilmenee, ota meihin yhteyttä sähköpostitse.

Mail To:help@itsvse.com