Delen via


Methode ICorProfilerInfo2::D oStackSnapshot

Begeleidt de beheerde frames op de stack voor de opgegeven thread en verzendt informatie naar de profiler via een callback.

Syntaxis

HRESULT DoStackSnapshot(  
    [in] ThreadID thread,  
    [in] StackSnapshotCallback *callback,  
    [in] ULONG32 infoFlags,  
    [in] void *clientData,  
    [in, size_is(contextSize), length_is(contextSize)] BYTE context[],  
    [in] ULONG32 contextSize);  

Parameters

thread
[in] De id van de doelthread.

Het doorgeven van null in thread levert een momentopname van de huidige thread op. Als een ThreadID van een andere thread wordt doorgegeven, onderbreekt de COMMON Language Runtime (CLR) die thread, voert de momentopname uit en wordt deze hervat.

callback
[in] Een verwijzing naar de implementatie van de StackSnapshotCallback-methode , die wordt aangeroepen door de CLR om de profiler te voorzien van informatie over elk beheerd frame en elke uitvoering van niet-beheerde frames.

De StackSnapshotCallback methode wordt geïmplementeerd door de profiler writer.

infoFlags
[in] Een waarde van de COR_PRF_SNAPSHOT_INFO opsomming, die de hoeveelheid gegevens aangeeft die voor elk frame moet worden doorgestuurd door StackSnapshotCallback.

clientData
[in] Een aanwijzer naar de clientgegevens, die rechtstreeks worden doorgegeven aan de StackSnapshotCallback callback-functie.

context
[in] Een verwijzing naar een Win32-structuur CONTEXT , die wordt gebruikt om de stack walk te seeden. De Win32-structuur CONTEXT bevat waarden van de CPU-registers en vertegenwoordigt de status van de CPU op een bepaald moment in de tijd.

De seed helpt de CLR te bepalen waar de stack-walk moet beginnen, als de bovenkant van de stack onbeheerde helpercode is; anders wordt het zaadje genegeerd. Een zaadje moet worden geleverd voor een asynchrone wandeling. Als je een synchrone wandeling doet, is er geen zaadje nodig.

De context parameter is alleen geldig als de vlag COR_PRF_SNAPSHOT_CONTEXT is doorgegeven in de infoFlags parameter .

contextSize
[in] De grootte van de CONTEXT structuur, waarnaar wordt verwezen door de context parameter .

Opmerkingen

Het doorgeven van null voor thread levert een momentopname van de huidige thread op. Momentopnamen van andere threads kunnen alleen worden gemaakt als de doelthread op dat moment is onderbroken.

Wanneer de profiler de stack wil doorlopen, wordt aangeroepen DoStackSnapshot. Voordat de CLR van die aanroep terugkeert, wordt uw StackSnapshotCallback meerdere keren aangeroepen, één keer voor elk beheerd frame (of uitvoering van niet-beheerde frames) op de stack. Wanneer onbeheerde frames worden aangetroffen, moet u deze zelf doorlopen.

De volgorde waarin de stapel wordt doorlopen, is het omgekeerde van de wijze waarop de frames op de stapel zijn geduwd: frame eerst blad (laatst gepusht), hoofdframe (eerst geduwd) als laatste.

Zie Profiler Stack Walking in de .NET Framework 2.0: Basics and Beyond voor meer informatie over het programmeren van de profiler om beheerde stacks te doorlopen.

Een stack-walk kan synchroon of asynchroon zijn, zoals wordt uitgelegd in de volgende secties.

Synchrone stack walk

Een synchrone stack-walk omvat het doorlopen van de stack van de huidige thread als reactie op een callback. Het vereist geen seeding of suspending.

U voert een synchrone aanroep uit wanneer u, in reactie op de CLR die een van de ICorProfilerCallback-methoden (of ICorProfilerCallback2) van uw profiler aanroept DoStackSnapshot om de stack van de huidige thread te doorlopen. Dit is handig als u wilt zien hoe de stack eruitziet bij een melding zoals ICorProfilerCallback::ObjectAllocated. U roept DoStackSnapshot gewoon aan vanuit uw ICorProfilerCallback methode en geeft null door in de context parameters en thread .

Asynchrone stack walk

Een asynchrone stack-walk omvat het lopen van de stack van een andere thread of het lopen van de stack van de huidige thread, niet als reactie op een callback, maar door het kapen van de instructieaanwijzer van de huidige thread. Een asynchrone walk vereist een seed als de bovenkant van de stack onbeheerde code is die geen deel uitmaakt van een platformaanroep (PInvoke) of COM-aanroep, maar helpercode in de CLR zelf. Code die bijvoorbeeld JIT-compilatie (Just-In-Time) of garbagecollection doet, is helpercode.

U verkrijgt een seed door de doelthread rechtstreeks te onderbreken en de stapel zelf te lopen, totdat u het bovenste beheerde frame hebt gevonden. Nadat de doelthread is onderbroken, haalt u de huidige registercontext van de doelthread op. Bepaal vervolgens of de registercontext verwijst naar niet-beheerde code door ICorProfilerInfo::GetFunctionFromIP aan te roepen. Als het een FunctionID gelijk aan nul retourneert, is het frame onbeheerde code. Loop nu door de stapel totdat u het eerste beheerde frame bereikt en bereken vervolgens de seed-context op basis van de registercontext voor dat frame.

Roep DoStackSnapshot aan met uw seed-context om de asynchrone stack-walk te starten. Als u geen seed opgeeft, DoStackSnapshot slaat u beheerde frames mogelijk over aan de bovenkant van de stapel en krijgt u daardoor een onvolledige stack-wandeling. Als u een seed opgeeft, moet deze verwijzen naar door JIT gecompileerde of door Native Image Generator (Ngen.exe) gegenereerde code; DoStackSnapshot retourneert anders de foutcode, CORPROF_E_STACKSNAPSHOT_UNMANAGED_CTX.

Asynchrone stack-wandelingen kunnen gemakkelijk impasses of toegangsschendingen veroorzaken, tenzij u deze richtlijnen volgt:

  • Wanneer u threads rechtstreeks onderbreekt, moet u er rekening mee houden dat alleen een thread die nog nooit beheerde code heeft uitgevoerd, een andere thread kan onderbreken.

  • Blokkeer altijd uw ICorProfilerCallback::ThreadDestroyed callback totdat de stack-walk van die thread is voltooid.

  • Houd geen vergrendeling ingedrukt terwijl uw profiler een CLR-functie aanroept die een garbagecollection kan activeren. Dat wil zeggen, houd geen vergrendeling vast als de thread die eigenaar is mogelijk een aanroep doet die een garbagecollection activeert.

Er is ook een risico van impasse als u aanroept DoStackSnapshot vanuit een thread die uw profiler heeft gemaakt, zodat u de stapel van een afzonderlijke doelthread kunt doorlopen. De eerste keer dat de thread die u hebt gemaakt bepaalde ICorProfilerInfo* methoden invoert (waaronder DoStackSnapshot), voert de CLR per thread een CLR-specifieke initialisatie uit op die thread. Als uw profiler de doelthread waarvan u de stack probeert te doorlopen, heeft onderbroken en als die doelthread een vergrendeling heeft die nodig is voor het uitvoeren van deze initialisatie per thread, treedt er een impasse op. Om deze impasse te voorkomen, doet u een eerste aanroep vanuit DoStackSnapshot de door de profiler gemaakte thread om een afzonderlijke doelthread te doorlopen, maar onderbreekt u de doelthread niet eerst. Deze eerste aanroep zorgt ervoor dat de initialisatie per thread zonder impasse kan worden voltooid. Als DoStackSnapshot dit lukt en ten minste één frame rapporteert, is het na dat punt veilig voor die door de profiler gemaakte thread om een doelthread te onderbreken en aan te roepen DoStackSnapshot om de stapel van die doelthread te doorlopen.

Vereisten

Platforms: Zie Systeemvereisten.

Header: CorProf.idl, CorProf.h

Bibliotheek: CorGuids.lib

.NET Framework versies: beschikbaar sinds 2.0

Zie ook