Método ICorProfilerInfo2::D oStackSnapshot
Orienta as molduras geridas na pilha para o thread especificado e envia informações para o gerador de perfis através de uma chamada de retorno.
Sintaxe
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);
Parâmetros
thread
[in] O ID do thread de destino.
Transmitir nulo em thread
gera um instantâneo do thread atual. Se um ThreadID
de um thread diferente for transmitido, o runtime de idioma comum (CLR) suspende esse thread, executa o instantâneo e retoma.
callback
[in] Um ponteiro para a implementação do método StackSnapshotCallback , que é chamado pelo CLR para fornecer ao gerador de perfis informações sobre cada frame gerido e cada execução de frames não geridos.
O StackSnapshotCallback
método é implementado pelo escritor do profiler.
infoFlags
[in] Um valor da enumeração de COR_PRF_SNAPSHOT_INFO , que especifica a quantidade de dados a serem transmitidos para cada fotograma por StackSnapshotCallback
.
clientData
[in] Um ponteiro para os dados do cliente, que é transmitido diretamente para a StackSnapshotCallback
função de chamada de retorno.
context
[in] Um ponteiro para uma estrutura Win32 CONTEXT
, que é utilizada para propagar a caminhada da pilha. A estrutura Win32 CONTEXT
contém valores dos registos da CPU e representa o estado da CPU num determinado momento.
A semente ajuda o CLR a determinar onde iniciar a caminhada da pilha, se a parte superior da pilha for código auxiliar não gerido; caso contrário, a semente é ignorada. Tem de ser fornecida uma semente para uma caminhada assíncrona. Se estiver a fazer uma caminhada síncrona, não é necessária nenhuma semente.
O context
parâmetro só é válido se o sinalizador de COR_PRF_SNAPSHOT_CONTEXT tiver sido transmitido no infoFlags
parâmetro.
contextSize
[in] O tamanho da CONTEXT
estrutura, que é referenciada pelo context
parâmetro.
Observações
Transmitir nulo para thread
produz um instantâneo do thread atual. Os instantâneos só podem ser tirados de outros threads se o thread de destino estiver suspenso no momento.
Quando o gerador de perfis quer andar na pilha, chama DoStackSnapshot
. Antes de o CLR regressar dessa chamada, chama a sua StackSnapshotCallback
várias vezes, uma vez para cada fotograma gerido (ou execução de fotogramas não geridos) na pilha. Quando são encontradas molduras não geridas, tem de guiá-las sozinho.
A ordem pela qual a pilha é andada é o inverso da forma como as molduras foram enviadas para a pilha: primeiro moldura de folha (último push), moldura principal (em primeiro lugar).
Para obter mais informações sobre como programar o gerador de perfis para andar em pilhas geridas, consulte Profiler Stack Walking in the .NET Framework 2.0: Basics and Beyond (Noções básicas e não só).
Uma caminhada em pilha pode ser síncrona ou assíncrona, conforme explicado nas secções seguintes.
Caminhada de Pilha Síncrona
Uma caminhada de pilha síncrona envolve andar na pilha do thread atual em resposta a uma chamada de retorno. Não requer a propagação nem a suspensão.
Efetua uma chamada síncrona quando, em resposta ao CLR que chama um dos métodos ICorProfilerCallback (ou ICorProfilerCallback2) do seu perfil, chama DoStackSnapshot
para percorrer a pilha do thread atual. Isto é útil quando pretender ver o aspeto da pilha numa notificação como ICorProfilerCallback::ObjectAllocated. Basta chamar DoStackSnapshot
a partir do seu ICorProfilerCallback
método, transmitindo nulo nos context
parâmetros e thread
.
Caminhada de Pilha Assíncrona
Uma caminhada de pilha assíncrona implica andar na pilha de um thread diferente, ou andar na pilha do thread atual, não em resposta a uma chamada de retorno, mas ao sequestrar o ponteiro de instruções do tópico atual. Uma caminhada assíncrona requer uma semente se a parte superior da pilha for um código não gerido que não faça parte de uma invocação de plataforma (PInvoke) ou chamada COM, mas código auxiliar no próprio CLR. Por exemplo, o código que faz a compilação just-in-time (JIT) ou a recolha de lixo é código auxiliar.
Obtém uma semente ao suspender diretamente o thread de destino e andar na pilha até encontrar a moldura gerida mais alta. Após a suspensão do thread de destino, obtenha o contexto de registo atual do thread de destino. Em seguida, determine se o contexto de registo aponta para código não gerido ao chamar ICorProfilerInfo::GetFunctionFromIP — se devolver um FunctionID
código igual a zero, a moldura não é gerida. Agora, ande na pilha até chegar à primeira moldura gerida e, em seguida, calcule o contexto de seed com base no contexto de registo dessa moldura.
Chame DoStackSnapshot
com o contexto de seed para iniciar a caminhada de pilha assíncrona. Se não fornecer uma semente, DoStackSnapshot
poderá ignorar as molduras geridas na parte superior da pilha e, consequentemente, dar-lhe-á uma caminhada de pilha incompleta. Se fornecer uma semente, esta tem de apontar para código gerado pelo Gerador de Imagens Nativo (Ngen.exe) compilado pelo JIT; caso contrário, DoStackSnapshot
devolve o código de falha CORPROF_E_STACKSNAPSHOT_UNMANAGED_CTX.
As caminhadas de pilhas assíncronas podem causar facilmente impasses ou violações de acesso, a menos que siga estas diretrizes:
Quando suspender diretamente threads, lembre-se de que apenas um thread que nunca executou código gerido pode suspender outro thread.
Bloqueie sempre a chamada de retorno ICorProfilerCallback::ThreadDestroyed até que a caminhada da pilha desse thread esteja concluída.
Não mantenha um bloqueio enquanto o seu gerador de perfis chama para uma função CLR que pode acionar uma libertação de lixo. Ou seja, não mantenha um bloqueio se o thread proprietário fizer uma chamada que acione uma coleção de lixo.
Existe também o risco de impasse se chamar DoStackSnapshot
a partir de um thread que o seu gerador de perfis criou para que possa percorrer a pilha de um thread de destino separado. A primeira vez que o thread que criou introduz determinados ICorProfilerInfo*
métodos (incluindo DoStackSnapshot
), o CLR realizará uma inicialização por thread, específica de CLR nesse thread. Se o seu gerador de perfis tiver suspendido o thread de destino cuja pilha está a tentar andar e se esse thread de destino tiver um bloqueio necessário para efetuar esta inicialização por thread, ocorrerá um impasse. Para evitar este impasse, faça uma chamada inicial a partir do thread criado pelo DoStackSnapshot
seu profiler para percorrer um thread de destino separado, mas não suspenda primeiro o thread de destino. Esta chamada inicial garante que a inicialização por thread pode ser concluída sem impasse. Se DoStackSnapshot
for bem-sucedido e comunicar, pelo menos, uma moldura, após esse ponto, será seguro que esse thread criado pelo profiler suspenda qualquer thread de destino e chame DoStackSnapshot
para percorrer a pilha desse thread de destino.
Requisitos
Plataformas: Veja Requisitos do Sistema.
Cabeçalho: CorProf.idl, CorProf.h
Biblioteca: CorGuids.lib
.NET Framework Versões: Disponível desde 2.0