2010-08-04 14 views
5

Soy nuevo en C++/CLI, así que tenga paciencia ...¿Cómo limpio cosas .NET cuando se descarga una DLL C++/CLI?

Estoy trabajando en una DLL mixta de C++/CLI, que debería actuar como un puente entre un proceso Win32 y un ensamblado .NET . En la DLL, necesito que algo de .NET esté presente durante la vida útil de la DLL. Inicializar no es un problema tan grande, pero no pude averiguar cuándo puedo limpiar de forma segura las cosas de .NET. Las instalaciones habituales de C++ (DLL_PROCESS_DETACH, variables globales y locales estáticos d'ors) parecen ser llamadas después de que el CLR se haya ido.

Entonces, ¿cuál es la manera de recibir notificaciones de que la DLL está a punto de separarse de la CLR, así que puedo liberar las referencias de .NET que tengo?

Respuesta

2

Bueno, respondiendo a mi propia pregunta parece torpe, pero esto no fue sugerido por cualquier otra persona, y es lo que estaba buscando ... así:

resulta Microsoft ofrece una variación exótica de onexit, llamado _onexit_m, que se debe utilizar en DLL de modo mixto. Cuando se usa _onexit_m para registrar una función de devolución de llamada (administrada), se llamará a esa función cuando la DLL esté a punto de descargarse, pero antes de que se haya cerrado el CLR. Es similar a AppDomain.DomainUnload, suggested by Ben Voigt, pero por alguna razón no pude conseguir DomainUnload funcione, y _onexit_m es más fácil de usar en mi humilde opinión.

0

Esto podría no aplicarse al lado C++ de .NET, pero que yo sepa, la única manera de hacer que CLR libere un ensamblaje cargado es deshacerse del dominio de la aplicación; y a menos que haya diseñado una administración de AppDomain manual, es probable que solo tenga el AppDomain inicial, lo que hace que la eliminación sea equivalente a eliminar su aplicación.

+0

No estoy tratando de liberar un ensamblado. Estoy intentando liberar las referencias a los objetos .NET que he creado, y he estado reteniendo durante la vida útil de la DLL ... – eran

+0

Están los objetos en. NET desechable En ese caso, puede probar dispose() en esos objetos una vez que termine el uso. – Kangkan

+0

@Kangkan - sabe cuando se termina el uso es exactamente mi problema ... Es fácil saber cuándo el mundo nativa está a punto de terminar (proceso de separar, globales d'tores etc.) pero en ese momento, el mundo ya ha logrado terminado – eran

0

.NET DLL debe ser tratado como conjunto de clases separadas ref. Cada instancia de la clase de referencia tiene su propia vida, y la administración de recursos se realiza en relación con la duración de la instancia de la clase. El patrón Dispose correctamente implementado resuelve todos los problemas de gestión de recursos.

Cada clase C++/CLI, que tiene algunos recursos nativos, o miembros de clase descartables, debe tener el destructor y el finalizador opcional. Específicamente, las referencias .NET se liberan en el destructor de clase, que se asigna al método C# Dispose.

+0

Probablemente mi problema sea utilizar el patrón incorrecto, pero no puedo encontrar el correcto. Piensa en mi caso como singleton nativo, que almacena una referencia a un objeto .NET en un auto_gcroot. Cuando se destruye el singleton, auto_gcroot intenta liberar la referencia, pero es demasiado tarde y provoca un bloqueo. – eran

+1

Si va a mantener el objeto mientras se carga el archivo DLL, simplemente "filtre" el identificador. El recolector de basura se encargará de resolverlo en el caso extremadamente improbable de que CLR siga ejecutándose después de que se descargue su DLL. –

+0

Supongo que mantiene la referencia auto_gcroot para algún tipo de comunicación de devolución de llamada desde un singleton nativo a objetos .NET. ¿Tal vez es mejor pensar en otro algoritmo de devolución de llamada, por ejemplo, basado en eventos nativos? –

2

Si necesita ocuparse de las descargas de AppDomain, use el evento AppDomain.DomainUnload para realizar la limpieza.

Como dice STW, las bibliotecas con código administrado nunca se pueden separar de un AppDomain, la única manera de desconectarlo de su proceso es descargar el AppDomain.

Si no está administrando AppDomains, solo filtre el recurso administrado (y purgue correctamente los recursos no administrados durante el proceso de separación). Mejor aún, diseñarlo como un software de bloqueo solo para que no se requiera ninguna limpieza.

+0

DomainUnload parece una ruta válida, y acabo de comenzar a explorarlo, pero todavía no he podido hacerlo funcionar. En cuanto a filtrar los recursos gestionados, estaría bien, pero es tan difícil como el problema original ... para evitar que se conviertan en gc'ed, debo tener referencias a esos objetos. Me encantaría poder lanzar esas referencias al descargar, pero esto tiene que hacerse mientras .NET aún esté disponible. Averiguar cuál es el momento correcto es exactamente mi problema ... – eran

+0

Puede evitar la recopilación de objetos simplemente llamando a 'GCHandle.Alloc'. Los recursos durarán hasta que se descargue una llamada correspondiente a 'GCHandle.Free' o el appdomain. –

Cuestiones relacionadas