Metodo ICorProfilerInfo2::DoStackSnapshot

Illustra i frame gestiti nello stack per il thread specificato e invia informazioni al profiler tramite un callback.

Sintassi

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);  

Parametri

thread
[in] ID del thread di destinazione.

Il passaggio di null in thread restituisce uno snapshot del thread corrente. Se viene passato un ThreadID oggetto di un thread diverso, Common Language Runtime (CLR) sospende tale thread, esegue lo snapshot e riprende.

callback
[in] Puntatore all'implementazione del metodo StackSnapshotCallback , chiamato da CLR per fornire al profiler informazioni su ogni frame gestito e su ogni esecuzione di fotogrammi non gestiti.

Il StackSnapshotCallback metodo viene implementato dal writer del profiler.

infoFlags
[in] Valore dell'enumerazione COR_PRF_SNAPSHOT_INFO , che specifica la quantità di dati da passare di nuovo per ogni frame da StackSnapshotCallback.

clientData
[in] Puntatore ai dati client, che viene passato direttamente alla StackSnapshotCallback funzione di callback.

context
[in] Puntatore a una struttura Win32 CONTEXT , usata per eseguire il seeding della procedura dettagliata dello stack. La struttura Win32 CONTEXT contiene i valori dei registri della CPU e rappresenta lo stato della CPU in un determinato momento.

Il valore di inizializzazione consente a CLR di determinare dove iniziare la procedura dettagliata dello stack, se la parte superiore dello stack è codice helper non gestito; in caso contrario, il valore di inizializzazione viene ignorato. È necessario specificare un valore di inizializzazione per una procedura asincrona. Se si esegue una procedura sincrona, non è necessario alcun valore di inizializzazione.

Il context parametro è valido solo se il flag COR_PRF_SNAPSHOT_CONTEXT è stato passato nel infoFlags parametro .

contextSize
[in] Dimensione della CONTEXT struttura a cui fa riferimento il context parametro .

Commenti

Il passaggio di Null per thread restituisce uno snapshot del thread corrente. È possibile creare snapshot di altri thread solo se il thread di destinazione è sospeso al momento.

Quando il profiler vuole percorrere lo stack, chiama DoStackSnapshot. Prima che CLR venga restituito da tale chiamata, chiama StackSnapshotCallback l'oggetto più volte, una volta per ogni frame gestito (o esecuzione di frame non gestiti) nello stack. Quando vengono rilevati fotogrammi non gestiti, è necessario camminare manualmente.

L'ordine in cui viene camminato lo stack è il contrario del modo in cui i fotogrammi sono stati inseriti nello stack: primo fotogramma foglia (ultima spinta), fotogramma principale (primo push).

Per altre informazioni su come programmare il profiler per esaminare gli stack gestiti, vedere Profiler Stack Walking in .NET Framework 2.0: Basics and Beyond.For more information about how to program the profiler to walk managed stacks, see Profiler Stack Walking in the .NET Framework 2.0: Basics and Beyond.

Una procedura dettagliata dello stack può essere sincrona o asincrona, come illustrato nelle sezioni seguenti.

Procedura dettagliata dello stack sincrono

Una procedura dettagliata dello stack sincrono implica l'esecuzione dello stack del thread corrente in risposta a un callback. Non richiede il seeding o la sospensione.

Si effettua una chiamata sincrona quando, in risposta a CLR che chiama uno dei metodi ICorProfilerCallback (o ICorProfilerCallback2) del profiler, viene chiamato DoStackSnapshot per esaminare lo stack del thread corrente. Ciò è utile quando si vuole visualizzare l'aspetto dello stack in una notifica, ad esempio ICorProfilerCallback::ObjectAllocated. È sufficiente chiamare DoStackSnapshot dall'interno del ICorProfilerCallback metodo, passando null nei context parametri e thread .

Procedura dettagliata dello stack asincrono

Una procedura dettagliata dello stack asincrono comporta l'esecuzione dello stack di un thread diverso o il passaggio dello stack del thread corrente, non in risposta a un callback, ma eseguendo il dirottamento del puntatore all'istruzione del thread corrente. Una procedura asincrona richiede un valore di inizializzazione se l'inizio dello stack è codice non gestito che non fa parte di una chiamata platform invoke (PInvoke) o COM, ma il codice helper in CLR stesso. Ad esempio, il codice che esegue la compilazione JIT (Just-In-Time) o Garbage Collection è il codice helper.

Per ottenere un valore di inizializzazione, sospendere direttamente il thread di destinazione e camminare manualmente, fino a trovare il frame più gestito. Dopo aver sospeso il thread di destinazione, ottenere il contesto di registro corrente del thread di destinazione. Determinare quindi se il contesto del registro punta al codice non gestito chiamando ICorProfilerInfo::GetFunctionFromIP , se restituisce uno FunctionID uguale a zero, il frame è codice non gestito. A questo scopo, esaminare lo stack fino a raggiungere il primo frame gestito e quindi calcolare il contesto di inizializzazione in base al contesto del registro per tale frame.

Chiamare DoStackSnapshot con il contesto di inizializzazione per avviare la procedura dettagliata dello stack asincrono. Se non si specifica un valore di inizializzazione, DoStackSnapshot è possibile ignorare i fotogrammi gestiti nella parte superiore dello stack e, di conseguenza, vi darà una procedura dettagliata dello stack incompleta. Se si specifica un valore di inizializzazione, deve puntare al codice generato da JIT o native Image Generator (Ngen.exe); in caso contrario, DoStackSnapshot restituisce il codice di errore CORPROF_E_STACKSNAPSHOT_UNMANAGED_CTX.

Le procedure asincrone dello stack possono causare facilmente deadlock o violazioni di accesso, a meno che non si seguano queste linee guida:

  • Quando si sospendono direttamente i thread, tenere presente che solo un thread che non ha mai eseguito codice gestito può sospendere un altro thread.

  • Blocca sempre nel callback ICorProfilerCallback::ThreadDestroyed fino al completamento della procedura dettagliata dello stack del thread.

  • Non tenere premuto un blocco mentre il profiler chiama in una funzione CLR che può attivare un'operazione di Garbage Collection. Ovvero, non tenere premuto un blocco se il thread proprietario potrebbe effettuare una chiamata che attiva un'operazione di Garbage Collection.

Esiste anche il rischio di deadlock se si chiama DoStackSnapshot da un thread creato dal profiler in modo da poter camminare lo stack di un thread di destinazione separato. La prima volta che il thread creato immette determinati ICorProfilerInfo* metodi (incluso DoStackSnapshot), CLR eseguirà l'inizializzazione specifica di CLR per thread in tale thread. Se il profiler ha sospeso il thread di destinazione lo stack che si sta tentando di eseguire e se il thread di destinazione è proprietario di un blocco necessario per eseguire questa inizializzazione per thread, si verificherà un deadlock. Per evitare questo deadlock, effettuare prima una chiamata DoStackSnapshot iniziale dal thread creato dal profiler per eseguire un thread di destinazione separato, ma non sospendere prima il thread di destinazione. Questa chiamata iniziale garantisce che l'inizializzazione per thread possa essere completata senza deadlock. Se DoStackSnapshot ha esito positivo e segnala almeno un frame, dopo tale punto, sarà sicuro che tale thread creato dal profiler sospende qualsiasi thread di destinazione e chiama DoStackSnapshot per camminare nello stack di quel thread di destinazione.

Requisiti

Piattaforme: vedere Requisiti di sistema di .NET Framework.

Intestazione: CorProf.idl, CorProf.h

Libreria: CorGuids.lib

Versioni di .NET Framework: Disponibile dalla versione 2.0

Vedi anche