Anteckning
Åtkomst till den här sidan kräver auktorisering. Du kan prova att logga in eller ändra kataloger.
Åtkomst till den här sidan kräver auktorisering. Du kan prova att ändra kataloger.
Den här handledningen visar hur du använder vyn Uppgifter i fönstret Parallella staplar för att felsöka en C#-asynkron applikation. Det här fönstret hjälper dig att förstå och verifiera körningsbeteendet för kod som använder mönstret async/await, även kallat det aktivitetsbaserade asynkrona mönstret (TAP).
För appar som använder TPL (Task Parallel Library) men inte mönstret async/await, eller för C++-appar som använder Samtidighetskörning, använder du vyn Trådar i fönstret Parallella staplar för felsökning. Mer information finns i Felsöka ett dödläge och Visa trådar och uppgifter i fönstret Parallella staplar.
Uppgiftsvyn hjälper dig att:
- Visa anropsstackens visualiseringar för appar som använder mönstret async/await. I dessa scenarier ger vyn "Uppgifter" en mer komplett bild av applikationens tillstånd. 
- Identifiera asynkron kod som är schemalagd att köras men som ännu inte körs. En HTTP-begäran som inte har returnerat några data är till exempel mer sannolikt att visas i vyn Uppgifter i stället för vyn Trådar, vilket hjälper dig att isolera problemet. 
- Hjälp med att identifiera problem som sync-over-async-mönstret tillsammans med tips som rör potentiella problem, till exempel blockerade eller väntande uppgifter. Kodmönstret sync-over-async refererar till kod som anropar asynkrona metoder på ett synkront sätt, vilket är känt för att blockera trådar och är den vanligaste orsaken till utsvulten trådpool. 
Asynkrona anropsstackar
Uppgiftsvyn i Parallella Staplar ger en visualisering av asynkrona anropsstackar, så att du kan se vad som händer (eller ska hända) i ditt program.
Här följer några viktiga punkter att komma ihåg när du tolkar data i vyn Uppgifter.
- Asynkrona anropsstackar är logiska eller virtuella anropsstackar, inte fysiska anropsstackar som representerar stacken. När du arbetar med asynkron kod (till exempel med hjälp av nyckelordet - await) ger felsökningsprogrammet en vy över "asynkrona anropsstackar" eller "virtuella anropsstackar". Asynkrona anropsstackar skiljer sig från trådbaserade anropsstackar eller "fysiska staplar", eftersom asynkrona anropsstackar inte nödvändigtvis körs på någon fysisk tråd. I stället är asynkrona anropsstackar fortsättningar eller "löften" för kod som kommer att köras i framtiden, asynkront. Anropsstackarna skapas med fortsättningar.
- Asynkron kod som är schemalagd men inte körs för närvarande visas inte i den fysiska anropsstacken, men bör visas i den asynkrona anropsstacken i Tasks-vyn. Om du blockerar trådar med metoder som - .Waiteller- .Resultkan du se koden i den fysiska anropsstacken i stället.
- Asynkrona virtuella anropsstackar är inte alltid intuitiva på grund av förgrening som beror på användning av metodanrop som - .WaitAnyeller- .WaitAll.
- Fönstret Anropsstack kan vara användbart i kombination med vyn Arbetsuppgifter, eftersom det visar den fysiska anropsstacken för den aktuella körtråden. 
- Identiska delar av den virtuella anropsstacken grupperas tillsammans för att förenkla visualiseringen för komplexa appar. - Följande konceptuella animering visar hur gruppering tillämpas på virtuella anropsstackar. Endast identiska segment i en virtuell anropsstack grupperas. Hovra över en grupperad anropsstack för att identifiera de trådar som utför uppgifterna.   
C#-exempel
Exempelkoden i den här genomgången är för ett program som simulerar en dag i en gorillas liv. Syftet med övningen är att förstå hur du använder Uppgiftsvyn i fönstret Parallella staplar för att felsöka en asynkron applikation.
Exemplet innehåller ett exempel på hur du använder antimönstret sync-over-async, vilket kan resultera i utsvulten trådpool.
För att göra anropsstacken intuitiv utför exempelappen följande sekventiella steg:
- Skapar ett objekt som representerar en gorilla.
- Gorilla vaknar.
- Gorillan går på en morgonpromenad.
- Gorilla hittar bananer i djungeln.
- Gorilla äter.
- Gorilla sysslar med rackartyg.
Skapa exempelprojektet
- Öppna Visual Studio och skapa ett nytt projekt. - Om startfönstret inte är öppet väljer du Fil>Startfönster. - I startfönstret väljer du Nytt projekt. - I fönstret Skapa ett nytt projekt anger eller skriver du konsolen i sökrutan. Välj sedan C# i listan Språk och välj sedan Windows i listan Plattform. - När du har tillämpat språk- och plattformsfilter väljer du Konsolapp för .NET och sedan Nästa. - Anmärkning - Om du inte ser rätt mall går du till Verktyg>Hämta verktyg och funktioner... som öppnar Installationsprogrammet för Visual Studio. Välj arbetsbelastningen för .NET-skrivbordsutveckling och välj då Ändra. - I fönstret Konfigurera det nya projektet skriver du ett namn eller använder standardnamnet i rutan Projektnamn . Välj sedan Nästa. - För .NET väljer du antingen det rekommenderade målramverket eller .NET 8 och väljer sedan Skapa. - Ett nytt konsolprojekt visas. När projektet har skapats visas en källfil. 
- Öppna .cs kodfilen i projektet. Ta bort innehållet för att skapa en tom kodfil. 
- Klistra in följande kod för det valda språket i den tomma kodfilen. - using System.Diagnostics; namespace AsyncTasks_SyncOverAsync { class Jungle { public static async Task<int> FindBananas() { await Task.Delay(1000); Console.WriteLine("Got bananas."); return 0; } static async Task Gorilla_Start() { Debugger.Break(); Gorilla koko = new Gorilla(); int result = await Task.Run(koko.WakeUp); } static async Task Main(string[] args) { List<Task> tasks = new List<Task>(); for (int i = 0; i < 2; i++) { Task task = Gorilla_Start(); tasks.Add(task); } await Task.WhenAll(tasks); } } class Gorilla { public async Task<int> WakeUp() { int myResult = await MorningWalk(); return myResult; } public async Task<int> MorningWalk() { int myResult = await Jungle.FindBananas(); GobbleUpBananas(myResult); return myResult; } /// <summary> /// Calls a .Wait. /// </summary> public void GobbleUpBananas(int food) { Console.WriteLine("Trying to gobble up food synchronously..."); Task mb = DoSomeMonkeyBusiness(); mb.Wait(); } public async Task DoSomeMonkeyBusiness() { Debugger.Break(); while (!System.Diagnostics.Debugger.IsAttached) { Thread.Sleep(100); } await Task.Delay(30000); Console.WriteLine("Monkey business done"); } } }- När du har uppdaterat kodfilen sparar du ändringarna och skapar lösningen. 
- På menyn Arkiv väljer du Spara alla. 
- På menyn Build väljer du Build Solution. 
Använd uppgiftsvyn i fönstret Parallella staplar
- På menyn Felsök väljer du Starta felsökning (eller F5) och väntar på att den första - Debugger.Break()ska slås.
- Tryck på F5 en gång så pausar felsökningsprogrammet igen på samma - Debugger.Break()rad.- Detta pausar vid det andra anropet till - Gorilla_Start, som inträffar inom en andra asynkron uppgift.
- Välj Felsöka > Windows > Parallel Stacks för att öppna fönstret Parallella staplar och välj sedan Uppgifter i listrutan Visa i fönstret.   - Observera att etiketterna för asynkrona anropsstackar beskriver 2 asynkrona logiska staplar. När du senast tryckte på F5 startade du en annan uppgift. För förenkling i komplexa appar grupperas identiska asynkrona anropsstackar i en enda visuell representation. Detta ger mer fullständig information, särskilt i scenarier med många uppgifter. - Till skillnad från uppgiftsvyn visar fönstret Anropsstack endast anropsstacken för den aktuella tråden, inte för flera uppgifter. Det är ofta bra att visa dem båda tillsammans för en mer fullständig bild av apptillståndet.   - Tips/Råd - Fönstret Samtalsstack kan visa information, till exempel ett dödläge, med hjälp av beskrivningen - Async cycle.- Under felsökningen kan du ändra om extern kod ska visas. Om du vill växla funktionen högerklickar du på tabellrubriken Namn i fönstret Anropa stack och väljer eller avmarkerar sedan Visa extern kod. Om du visar extern kod kan du fortfarande använda den här genomgången, men dina resultat kan skilja sig från illustrationerna. 
- Tryck på F5 igen och felsökningsprogrammet pausar i - DoSomeMonkeyBusiness-metoden.  - Den här vyn visar en mer komplett asynkron anropsstack efter att fler asynkrona metoder har lagts till i den interna fortsättningskedjan, vilket inträffar när du använder - awaitoch liknande metoder.- DoSomeMonkeyBusinesskan eller kanske inte finnas överst i den asynkrona anropsstacken eftersom det är en asynkron metod, men ännu inte har lagts till i fortsättningskedjan. Vi kommer att undersöka varför så är fallet i de steg som följer.- Den här vyn visar också ikonen för - Jungle.Main som är blockerad. Detta är informativt, men tyder vanligtvis inte på något problem. En blockerad uppgift är en uppgift som blockeras eftersom den väntar på att en annan uppgift ska slutföras, en händelse som ska signaleras eller ett lås som ska släppas. som är blockerad. Detta är informativt, men tyder vanligtvis inte på något problem. En blockerad uppgift är en uppgift som blockeras eftersom den väntar på att en annan uppgift ska slutföras, en händelse som ska signaleras eller ett lås som ska släppas.
- Hovra över - GobbleUpBananasmetoden för att få information om de två trådar som kör aktiviteterna.  - Den aktuella tråden visas också i listan Tråd i verktygsfältet Felsökning.   - Du kan använda trådlistan för att växla felsökningskontexten till en annan tråd. 
- Tryck på F5 igen så pausar - DoSomeMonkeyBusinessfelsökningsprogrammet metoden för den andra aktiviteten.  - Beroende på tidpunkten för aktivitetskörningen ser du i det här läget antingen separata eller grupperade asynkrona anropsstackar. - I föregående bild är asynkrona anropsstackar för de två uppgifterna separata eftersom de inte är identiska. 
- Tryck på F5 igen så visas en lång fördröjning och vyn Uppgifter visar ingen asynkron anropsstackinformation. - Fördröjningen orsakas av en långvarig aktivitet. I det här exemplet simuleras en tidskrävande uppgift, till exempel en webbbegäran, vilket kan leda till att trådpoolen svälter. Ingenting visas i vyn Uppgifter eftersom du för närvarande inte har pausat felsökningsprogrammet, trots att uppgifter kan blockeras. - Tips/Råd - Knappen Bryt alla är ett bra sätt att få information om anropsstacken om ett dödläge inträffar eller om alla tasker och trådar för närvarande blockeras. 
- Längst upp i IDE:t i verktygsfältet Felsökning väljer du knappen Bryt alla (pausikon), Ctrl + Alt + Bryt.   - Nära toppen av asynkron anropsstacken i Uppgifter-vyn ser du att - GobbleUpBananasär blockerad. I själva verket blockeras två uppgifter vid samma tidpunkt. En blockerad uppgift är inte nödvändigtvis oväntad och innebär inte nödvändigtvis att det finns ett problem. Den observerade fördröjningen i körningen indikerar dock ett problem, och informationen om anropsstacken här visar platsen för problemet.- På vänster sida av föregående skärmbild anger den curlade gröna pilen den aktuella felsökningskontexten. De två uppgifterna blockeras - mb.Wait()i- GobbleUpBananas-metoden.- Fönstret Samtalsstack visar också att den aktuella tråden är blockerad.   - Anropet till - Wait()blockerar trådarna i det synkrona anropet till- GobbleUpBananas. Det här är ett exempel på antimönstret sync-over-async, och om detta inträffade i en UI-tråd eller under stora bearbetningsarbetsbelastningar skulle det vanligtvis åtgärdas med en kodkorrigering med hjälp av- await. Mer information finns i Felsöka utsvulten trådpool. Information om hur du använder profileringsverktyg för att felsöka utsvulten trådpool finns i Fallstudie: Isolera ett prestandaproblem.- Det är också av intresse att - DoSomeMonkeyBusinessinte visas på anropsstacken. Det är för närvarande schemalagt, körs inte, så det visas bara i asynkron anropsstacken i vyn Uppgifter.- Tips/Råd - Felsökningsprogrammet bryter sig in i kod per tråd. Det innebär till exempel att om du trycker på F5 för att fortsätta körningen och appen når nästa brytpunkt kan den brytas in i kod i en annan tråd. Om du behöver hantera detta i felsökningssyfte kan du lägga till ytterligare brytpunkter, lägga till villkorsstyrda brytpunkter eller använda Bryt alla. Mer information om det här beteendet finns i Följ en enda tråd med villkorsstyrda brytpunkter. 
Åtgärda exempelkoden
- GobbleUpBananasErsätt metoden med följande kod.- public async Task GobbleUpBananas(int food) // Previously returned void. { Console.WriteLine("Trying to gobble up food..."); //Task mb = DoSomeMonkeyBusiness(); //mb.Wait(); await DoSomeMonkeyBusiness(); }
- I - MorningWalk-metoden anropar du GobbleUpBananas med- await.- await GobbleUpBananas(myResult);
- Välj knappen Starta om (Ctrl + Skift + F5) och tryck sedan på F5 flera gånger tills appen visas som "låser sig". 
- Tryck på Bryt alla. - Den här gången - GobbleUpBananaskörs asynkront. När du bryter visas asynkron anropsstacken.  - Fönstret Samtalsstack är tomt förutom posten - ExternalCode.- Kodredigeraren visar ingenting, förutom att det innehåller ett meddelande som anger att alla trådar kör extern kod. - Uppgiftvyn ger dock användbar information. - DoSomeMonkeyBusinessär överst i asynkron anropsstacken, som förväntat. Detta anger korrekt var den långvariga metoden finns. Det här är användbart för att isolera async/await-problem när den fysiska anropsstacken i fönstret Samtalsstack inte ger tillräcklig information.
Sammanfattning
Den här genomgången visade felsökningsfönstret Parallel Stacks . Använd det här fönstret på appar som använder mönstret async/await.