2011-07-18 18 views
9

Los finalizadores siempre son llamados por .NET Framework, por lo que la secuencia podría estar fuera de control; e incluso si el constructor falló, el destructor todavía se puede activar.C#: ¿Cómo manejar las excepciones del finalizador de una biblioteca de terceros?

Esto podría traer problemas, cuando tales excepciones de finalizador provienen de una biblioteca de terceros: ¡No puedo encontrar una manera de manejarlos!

Por ejemplo, en el código siguiente, aunque el constructor de la clase A siempre lanza una excepción y falla, el finalizador de A será activado por .NET framework, también ~ B() se llama como A tiene una propiedad de tipo B .

class Program // my code 
{ 
    static void Main(string[] args) 
    { 
     A objA; 
     try 
     { 
      objA = new A(); 
     } 
     catch (Exception) 
     { 
     } 

     ; // when A() throws an exception, objA is null 

     GC.Collect(); // however, this can force ~A() and ~B() to be called. 

     Console.ReadLine(); 
    } 
} 

public class A // 3rd-party code 
{ 
    public B objB; 

    public A() 
    { 
     objB = new B(); // this will lead ~B() to be called. 
     throw new Exception("Exception in A()"); 
    } 

    ~A() // called by .net framework 
    { 
     throw new Exception("Exception in ~A()"); // bad coding but I can't modify 
    } 
} 

public class B // 3rd-party code 
{ 
    public B() { } 

    ~B() // called by .net framework 
    { 
     throw new Exception("Exception in ~B()"); // bad coding but I can't modify 
    } 
} 

Si estos son mi código, que es un poco más fácil - Puedo usar try-catch en finalizadores, al menos puedo hacer algo de tala - puedo permitir que la excepción se bloquee el programa, para descubrir el error asap - o si quiero "tolerar" la excepción, puedo tener un try-catch para suprimir la excepción, y tener una salida elegante.

Pero si A y B son clases de una biblioteca de terceros, ¡no puedo hacer nada! No puedo controlar la excepción, no puedo verlos, así que no puedo registrarla o suprimirla.

¿Qué puedo hacer?

+1

+1 Problema interesante (y mientras tanto, genera un informe de error urgente con los proveedores de la biblioteca que suministra 'A' y' B'). – Ergwun

+0

^^ - Gran punto. Necesita ser una respuesta real. –

Respuesta

0

Es posible que desee considerar un controlador de excepción global para su aplicación. Usted no indicó si su hacer ASP.NET, WinForm, MVC, etc, pero aquí está uno para una aplicación de consola:

.NET Global exception handler in console application

En ASP.NET, puede utilizar el archivo Global.asax para capturar excepciones no controladas.

Si siempre llama a GC.Collect() en su aplicación, puede intentar incluir eso en un bloque try-catch también.

Sólo algunas ideas a considerar.

0

Puede utilizar GC.SuppressFinalizer(objA) y GC.KeepAlive(objA) lo que evitará que el recolector de basura de llamar a la finalización de ese objeto, y por lo tanto cuando se utiliza el KeepAliveobjB no finalizará porque objA "que está vivo" es todavía tiene referencia de la misma. sin embargo, debe tener en cuenta pérdidas de memoria si olvida finalizar o eliminar objA de manera adecuada.

Pero supongamos que el objA en algún punto de un método, por ejemplo, ha inicializado otro objectB y no lo dispone correctamente, entonces desafortunadamente no creo que pueda hacer nada al respecto.

Otra cosa que puedes probar es comprobar si esa biblioteca se comporta de manera diferente cuando estás en el modo Release en lugar del modo Debug; por ejemplo, tal vez solo lanzan una excepción en el finalizador si se llama en modo de depuración "es una especie de ayuda para los desarrolladores por lo que si no llaman eliminan o finalizan el objeto de manera correcta una excepción arrojará durante la depuración":

~A() 
{ 
#if DEBUG 
    throw new Exception("Exception in ~A()"); 
#endif//DEBUG 
} 

Si ese no es el caso, entonces creo que tendrá un mal día lidiando con esa biblioteca.

+0

lo siento Jordan, creo que no hice mi pregunta con claridad, para que pueda tener un malentendido al respecto. – athos

+0

@athos: ¡Lo siento, leí su pregunta nuevamente y descubrí que me perdí el hecho de que el 'objA' es nulo! –

Cuestiones relacionadas