callbackOnCollectedDelegate MDA
The callbackOnCollectedDelegate Assistente de depuração gerenciada (MDA) será ativado se um delegado empacotado de gerenciado para código não gerenciado sistema autônomo um ponteiro de função e um retorno de chamada é colocado desse ponteiro de função depois que o delegado for coletados pelo lixo.
Sintomas
Violações de acesso ocorrem durante a tentativa de telefonar código gerenciado através de ponteiros de função que foram obtidas a partir de delegados gerenciados.Essas falhas, ao mesmo tempo não comuns linguagem tempo de execução (CLR) bugs, poderá parecer fazer isso porque a violação de acesso ocorre no código do CLR.
A falha não é consistente; às vezes, telefonar no ponteiro de função for bem-sucedida e às vezes não.A falha pode ocorrer somente sob carga pesada ou em um número aleatório de tentativas.
Causa
O delegado a partir do qual o ponteiro de função foi criado e exposto a código não gerenciado estava coletados pelo lixo.Quando o componente não gerenciado tenta chamar no ponteiro de função, ele gera uma violação de acesso.
A falha aparece aleatória porque ele depende de quando lixo coleção ocorre.Se um delegado é qualificado para coleção, o lixo coleção podem ocorrer após o retorno de telefonar e a telefonar for bem-sucedida.Em outros momentos, o lixo coleção ocorre antes do retorno de chamada, o retorno de chamada gera uma violação de acesso e o programa pára.
A probabilidade da falha depende do time entre o delegado e o retorno de chamada no ponteiro de função, bem sistema autônomo a freqüência das coletas de marshaling.A falha é esporádica se o time entre o delegado e o retorno de chamada exibido de marshaling for curto.Isso geralmente é o caso se o método não gerenciado, recebendo o ponteiro de função não salva o ponteiro de função para uso posterior, mas em vez disso, chama de volta no ponteiro de função imediatamente para concluir sua operação antes de retornar.Da mesma forma, mais lixo coleção s ocorrer quando um sistema está sob carga pesada, o que torna mais provável que um lixo coleção ocorrerá antes do retorno de chamada.
Resolução
Depois de um delegado foi empacotado sistema autônomo um ponteiro de função não gerenciada, o coletor de lixo não pode controlar sua tempo de vida.Em vez disso, seu código deve manter uma referência ao delegado durante o tempo de vida do ponteiro de função não gerenciada.Mas, antes você pode fazer isso, você primeiro deve identificar delegado que foi coletado.Quando o MDA é ativado, ele fornece o nome do tipo do delegado.Use o nome de Pesquisar chamar seu código de plataforma ou COM assinaturas que passam esse delegado check-out para código não gerenciado.O delegado ofensivo é passado um desses sites de telefonar.Você também pode ativar o gcUnmanagedToManaged MDA para forçar um lixo coleção antes de cada retorno de chamada no tempo de execução. Isso removerá a incerteza introduzida pela coleta de lixo, garantindo sempre uma coleta de lixo ocorre antes do retorno de chamada.Você sabe qual delegado foi coletado, altere o código para manter uma referência a esse delegado no lado gerenciado durante a tempo de vida do ponteiro de função não gerenciada empacotado.
Efeito sobre o tempo de execução
Quando delegados são empacotados sistema autônomo ponteiros de função, o tempo de execução aloca uma conversão que faz a transição de não gerenciado a gerenciado.Essa conversão é o que o código não gerenciado realmente chama antes do gerenciado delegado é chamado por último.Sem o callbackOnCollectedDelegate MDA ativada, o código de marshaling não gerenciado é excluído quando o delegado é coletado. Com o callbackOnCollectedDelegate MDA ativada, o código de marshaling não gerenciado não é excluído imediatamente quando o delegado é coletado. Em vez disso, as instâncias de 1.000 pela última vez são mantidas vivas por padrão e alteradas para ativar o MDA quando chamado.A conversão intermediária eventualmente é excluída após a representantes mais empacotadas 1,001 são coletados.
Saída
O MDA informa o nome de tipo de delegado coletadas antes de um retorno de chamada foi tentado no seu ponteiro de função não gerenciada.
Configuração
O exemplo a seguir mostra as opções de configuração do aplicativo.Ele define o número de thunks que o MDA mantém vivo para 1.500.O padrão de listSize valor é 1.000, o mínimo é de 50 e o máximo é de 2.000.
<mdaConfig>
<assistants>
<callbackOnCollectedDelegate listSize="1500" />
</assistants>
</mdaConfig>
Exemplo
O exemplo a seguir demonstra uma situação que pode ativar este MDA:
// Library.cpp : Defines the unmanaged entry point for the DLL application.
#include "windows.h"
#include "stdio.h"
void (__stdcall *g_pfTarget)();
void __stdcall Initialize(void __stdcall pfTarget())
{
g_pfTarget = pfTarget;
}
void __stdcall Callback()
{
g_pfTarget();
}
// ---------------------------------------------------
// C# Client
using System;
using System.Runtime.InteropServices;
public class Entry
{
public delegate void DCallback();
public static void Main()
{
new Entry();
Initialize(Target);
GC.Collect();
GC.WaitForPendingFinalizers();
Callback();
}
public static void Target()
{
}
[DllImport("Library", CallingConvention = CallingConvention.StdCall)]
public static extern void Initialize(DCallback pfDelegate);
[DllImport ("Library", CallingConvention = CallingConvention.StdCall)]
public static extern void Callback();
~Entry() { Console.Error.WriteLine("Entry Collected"); }
}
Consulte também
Conceitos
Diagnosticar erros com assistentes de depuração gerenciadas
Visão geral do empacotamento interop