Partilhar via


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

Ver também