ICorProfilerInfo2::DoStackSnapshot (Método)
Recorre los marcos administrados en la pila para el subproceso especificado y envía información al generador de perfiles mediante una devolución de llamada.
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] Id. del subproceso de destino.Si se pasa null en thread, se genera una instantánea del subproceso actual. Si se pasa un ThreadID de un subproceso diferente, el Common Language Runtime (CLR) suspende ese subproceso, realiza la instantánea y continúa.
callback
[in] Puntero a la implementación del método StackSnapshotCallback, al que llama CLR para proporcionar información al generador de perfiles sobre cada marco administrado y cada ejecución de marcos no administrados.El escritor del generador de perfiles implementa el método StackSnapshotCallback.
infoFlags
[in] Valor de la enumeración COR_PRF_SNAPSHOT_INFO, que especifica la cantidad de datos que StackSnapshotCallback va a devolver para cada marco.clientData
[in] Puntero a los datos del cliente, que se pasa directamente a través de la función de devolución de llamada StackSnapshotCallback.context
[in] Puntero a una estructura CONTEXT de Win32, que se utiliza para inicializar el recorrido de pila. La estructura CONTEXT de Win32 contiene valores de los registros de la CPU y representa el estado de la CPU en un momento determinado.El valor de inicialización ayuda a CLR a determinar dónde comenzar el recorrido de pila, si la parte superior de la pila es código auxiliar no administrado; de lo contrario, se omite el valor de inicialización. Se debe proporcionar un valor de inicialización para los recorridos asincrónicos. Si está haciendo un recorrido sincrónico, no es necesario un valor de inicialización.
El parámetro context sólo es válido si el marcador COR_PRF_SNAPSHOT_CONTEXT se pasó en el parámetro infoFlags.
contextSize
[in] Tamaño de la estructura CONTEXT, a la que hace referencia el parámetro context.
Comentarios
Si se pasa null en thread, se genera una instantánea del subproceso actual. Sólo es posible tomar instantáneas de otros subprocesos si el subproceso de destino está suspendido en ese momento.
Cuando el generador de perfiles desea recorrer la pila, llama a DoStackSnapshot. Antes de que el CLR vuelva de esa llamada, llama a StackSnapshotCallback varias veces, una por cada marco administrado (o ejecución de marcos no administrados) de la pila. Cuando se encuentran marcos no administrados, debe recorrerlos usted.
La pila se recorre en orden inverso al orden de inserción de los marcos en la pila: primero, el marco de hoja (último insertado); en último lugar, el marco principal (primero insertado).
Para obtener más información sobre cómo programar el generador de perfiles para recorrer las pilas administradas, vea Profiler Stack Walking in the .NET Framework 2.0: Basics and Beyond en MSDN Library.
Un recorrido de pila puede ser sincrónico o asincrónico, como se explica en las secciones siguientes.
Recorrido de pila sincrónico
Un recorrido de pila sincrónico recorre la pila del subproceso actual en respuesta a una devolución de llamada. No requiere inicialización ni suspensión.
Se realiza una llamada sincrónica cuando, en respuesta a una llamada de CLR a uno de los métodos ICorProfilerCallback (o ICorProfilerCallback2) del generador de perfiles, se llama a DoStackSnapshot para recorrer la pila del subproceso actual. Esto resulta útil cuando se desea ver el aspecto de una pila en una notificación como ICorProfilerCallback::ObjectAllocated. Simplemente se llama a DoStackSnapshot desde el método ICorProfilerCallback, pasando null en los parámetros context y thread.
Recorrido de pila asincrónico
Un recorrido de pila asincrónico implica el recorrido de la pila de un subproceso diferente o el recorrido de la pila del subproceso actual, no en respuesta a una devolución de llamada, sino apropiándose del puntero de instrucciones del subproceso actual. Un recorrido asincrónico requiere un valor de inicialización si la parte superior de la pila es código no administrado que no forma parte de una invocación de la plataforma (PInvoke) o de una llamada COM, sino de código auxiliar en el propio CLR. Por ejemplo, el código que hace compilación just-in-time (JIT) o recolección de elementos no utilizados es código auxiliar.
Se obtiene un valor de inicialización suspendiendo directamente el subproceso de destino y recorriendo la pila usted mismo, hasta que encuentre el marco administrado superior. Una vez suspendido el subproceso de destino, obtenga el contexto del registro actual del subproceso de destino. Luego, determine si el contexto de registro señala código no administrado llamando a ICorProfilerInfo::GetFunctionFromIP: si devuelve un FunctionID igual a cero, el marco es código no administrado. Ahora, recorra la pila hasta que llegue al primer marco administrado y, a continuación, calcule el contexto del valor de inicialización basado en el contexto del registro para ese marco.
Llame a DoStackSnapshot con su contexto del valor de inicialización para comenzar el recorrido de pila asincrónico. Si no proporciona un valor de inicialización, DoStackSnapshot podría omitir los marcos administrados de la parte superior de la pila y, por consiguiente, hacer un recorrido de pila incompleto. Si proporciona un valor de inicialización, debe señalar a código compilado JIT o código de Generador de imágenes nativas (Ngen.exe); de lo contrario, DoStackSnapshot devuelve el código de error, CORPROF_E_STACKSNAPSHOT_UNMANAGED_CTX.
Los recorridos de pila asincrónicos pueden producir con facilidad interbloqueos o intentos de acceso no permitido, a menos que siga estas instrucciones:
Cuando suspende directamente los subprocesos, recuerde que sólo un subproceso que nunca ha ejecutado código administrado puede suspender otro subproceso.
Realice un bloqueo siempre en la devolución de llamada de ICorProfilerCallback::ThreadDestroyed hasta que el recorrido de pila de ese subproceso se haya completado.
No mantenga un bloqueo mientras el generador de perfiles llame a una función de CLR que pueda desencadenar una recolección de elementos no utilizados. Es decir, no mantenga un bloqueo si el subproceso propietario puede realizar una llamada que desencadene una recolección de elementos no utilizados.
Hay también un riesgo de interbloqueo si llama a DoStackSnapshot desde un subproceso que su generador de perfiles ha creado para que pueda recorrer la pila de un subproceso de destino diferente. La primera vez que el subproceso que creó entra en ciertos métodos ICorProfilerInfo* (incluyendo DoStackSnapshot), el CLR realizará la inicialización por subproceso específica del CLR en ese subproceso. Si el generador de perfiles ha suspendido el subproceso de destino cuyo pila intenta recorrer y si ese subproceso de destino posee un bloqueo necesario para realizar esta inicialización por subproceso, se producirá un interbloqueo. Para evitar este interbloqueo, haga una llamada inicial a DoStackSnapshot desde el subproceso creado por el generador de perfiles para recorrer un subproceso de destino diferente, pero no suspenda el subproceso de destino primero. Esta llamada inicial asegura que la inicialización por subproceso puede completarse sin interbloqueos. Si DoStackSnapshot se ejecuta correctamente y notifica al menos un marco, después de ese punto, ese subproceso creado por el generador de perfiles podrá suspender de forma segura cualquier subproceso de destino y llamar a DoStackSnapshot para recorrer la pila de ese subproceso de destino.
Requisitos
Plataformas: vea Requisitos de sistema de .NET Framework.
Encabezado: CorProf.idl, CorProf.h
Biblioteca: CorGuids.lib
Versiones de .NET Framework: 4, 3.5 SP1, 3.5, 3.0 SP1, 3.0, 2.0 SP1, 2.0