2011-08-22 7 views
5

Mi aplicación es una combinación de código C# y C++. El módulo de inicio escrito en C# se carga durante la fase de inicialización del módulo C++ a través del mecanismo COM (Modelo de Objetos Componentes). Todo estaba funcionando correctamente hasta que decidí agregar a C# parte un servicio wcf. Todas las llamadas de servicio wcf se enrutan a código C++ utilizando COM. Después de agregar algunos métodos nuevos noté pérdidas de memoria en la ventana de salida. Así que agregué el punto de interrupción al desctructor de la clase C++ como se puede ver en la captura de pantalla. A partir de este momento comenzaron a suceder cosas extrañas. Después de que el programa llega al punto de interrupción, inesperadamente se bloquea. Lo primero extraño es que cuando ejecuto un programa sin establecer un punto de interrupción, termina amablemente. Lo segundo extraño es que la forma en que se bloquea el programa es como si se estuviera ejecutando sin depurador. Después de hacer clic en el botón "Abrir en el depurador" (o algo así) recibo un mensaje de error: "El programa ya está abierto en el depurador". Ninguno mensaje en la ventana de salida que podría indicarme el origen del error, ningún código sospechoso. Al agregar el cuadro de mensaje al destructor comenzando, se muestra durante una fracción de segundo y luego se cierra toda la aplicación (sin agregar la oportunidad del usuario para leer lo que se muestra en el cuadro de mensaje). Buscando desesperadamente cualquier pista.Bloqueo extraño al depurar el destructor de objetos COM

P.S. Los problemas ocurren solo cuando se llama al método wcf al menos una vez. No depende si el flujo del programa en esta llamada en particular fue enrutado al nivel de C++ o no.

enter image description here

enter image description here

+0

Trate de usar WinDbg en lugar del depurador VS para obtener más información sobre el bloqueo – SpaceghostAli

Respuesta

0

resuelto por código siguiente:

public void Dispose() 
{ 
    Marshal.Release(internal_interface_ptr); 
    internal_interface_ptr = IntPtr.Zero; 
    Marshal.ReleaseComObject(internal_interface); 
    Marshal.ReleaseComObject(internal_interface); 
    internal_interface = null; 
} 

Al lado de esta otra referencia estaba colgando en código C++. Así que para concluir, el error principal de mi parte fue olvidarme de liberar explícitamente el objeto COM en el código C#. Incluso si el recolector de basura se encarga de administrar la memoria, esto no es cierto para los módulos escritos en otros lenguajes de programación. Se ha llamado al destructor COM muy recientemente cuando se iba a descargar una determinada biblioteca vinculada dinámica de la memoria y esto causaba problemas. Espero haberlo explicado suficientemente claro.

1

Al llamar desde C# C++ veces el recolector de basura no correctamente ser llamado antes del fin del programa. Intenta forzar la recolección de basura al final de tu código C#.

+0

Se estrelló como si el milagro se hubiera desvanecido, sin embargo el programa finaliza antes de que todos los destructores COM hayan terminado su trabajo. Ver mi segunda captura de pantalla. En este preciso momento, el programa se encuentra justo antes de su finalización, pero aún no se han invocado algunos destructores COM. Después de ser llamados, su trabajo se termina abruptamente. – truthseeker

+0

Se resolvió por el siguiente código: public void Dispose() { Marshal.Release (internal_interface_ptr); internal_interface_ptr = IntPtr.Zero; Marshal.ReleaseComObject (internal_interface); internal_interface = null; } – truthseeker

+0

No estoy muy seguro de lo que quiere decir con "Estrellarse como si el milagro desapareciera". Creo que es posible que necesites forzar tus servicios para que se deshagan antes de llamar al recopilador de garbas. Compruebe para asegurarse de que ya sea que se elimine ServicesToRun o los servicios antes de que se ejecute el recopilador de garbase, de lo contrario, ejecutarlo no le servirá de nada. – mydogisbox

Cuestiones relacionadas