2009-03-24 25 views
8

Tengo una clase que crea una instancia de un exe COM fuera de proceso. La clase esC# limpiar los recursos no administrados cuando se mata el proceso

public class MyComObject:IDisposable 
{ 
    private bool disposed = false; 
    MyMath test; 

    public MyComObject() 
    { 
     test = new MyMath(); 
    } 

    ~MyComObject() 
    { 
     Dispose(false); 
    } 

    public double GetRandomID() 
    { 
     if (test != null) 
      return test.RandomID(); 
     else 
      return -1; 
    } 

    public void Dispose() 
    { 
     Dispose(true); 

     GC.SuppressFinalize(this); 
    } 

    private void Dispose(bool disposing) 
    { 
     if (test != null) 
     { 
      Marshal.ReleaseComObject(test); 
      test = null; 
     } 

     disposed = true; 
    } 
} 

y me llaman de la siguiente manera

static void Main(string[] args) 
    { 
     MyComObject test = new MyComObject(); 
     MyComObject test2 = new MyComObject(); 

     //Do stuff 

     test.Dispose(); 
     test2.Dispose(); 

     Console.ReadLine(); 
    } 

ahora, esto se limpia mi objeto COM cuando el programa se ejecuta normalmente. Sin embargo, si cierro el programa en el medio de su ejecución, el framework nunca llama al código que libera mi objeto no administrado. Lo cual es justo. Sin embargo, ¿hay alguna manera de obligar al programa a que se limpie a sí mismo aunque haya sido asesinado?

EDIT: no se ve prometedor desde una muerte dura de la administrador de tareas :(

Respuesta

8

Envolverlo en un intento finalmente o utilizar la cláusula le llevará la mayor parte del camino allí :

using (MyComObject test = new MyComObject()) 
using (MyComObject test2 = new MyComObject()) { 
    // do stuff 
} 
Console.ReadLine(); 

Los detalles de how your app is being shutdown, sin embargo, dictará cualesquiera otras medidas que se pueden hacer (como el uso de CriticalFinalizerObject).

I piensan que una aplicación de consola que se cierra (de la pequeña x) es lo mismo que un Ctrl-C - en cuyo caso se puede subscribe to Console.CancelKeyPress para eso.

Editar: También debe ReleaseComObject until it returns <= 0.

5

Bueno, una buena práctica es utilizar using declaraciones:

using (MyComObject test = new MyComObject()) 
using (MyComObject test2 = new MyComObject()) 
{ 
    //Do stuff 
} 

que pone esencialmente en finally bloques de call disposee automáticamente al final del alcance. Debe tener using declaraciones casi siempre que tenga una instancia de IDisposable que se responsabilice de la limpieza. Sin embargo, no soluciona la situación en la que todo su proceso se interrumpe abruptamente. bastante raro sin embargo, y y Puede que no quieras preocuparte por eso. (Es bastante difícil evitarlo.) Tendría esperado el finalizador que se llamará con su código anterior, aunque ..

+0

que tampoco funciona. Los servidores COM se mantienen activos si elimino el proceso en el medio del bloque de uso. – Steve

+0

¿Cómo estás matando el proceso? ¿Has puesto algún registro en tus bloques de disposición para ver qué está pasando? –

+0

(Simplemente cerrar el programa con un apagado normal debería estar bien. Terminarlo desde el Administrador de tareas es probable que sea más desagradable.) ¿El servidor COM se apaga correctamente si cierra el programa de una manera "normal"? –

Cuestiones relacionadas