2008-10-27 16 views
15

Basado en toda mi lectura, debe haber un hilo GC para invocar a todos los finalizadores. Ahora, la pregunta es cuál es el alcance de este hilo "único", por proceso o por dominio de aplicación, ya que toda la intención de los dominios es separar y hacer diferentes aplicaciones "independientes" en un espacio de proceso.¿Cuál es el alcance del hilo del finalizador, por dominio de aplicación o por proceso?

leí here:

Si se produce una excepción no controlada en un finalizador del CLR ejecutar hilo se tragará la excepción, tratar el finalizador como si se completa normalmente, quitar de la cola freachable y pasar a la siguiente entrada.

más grave, sin embargo, es lo que sucede si su finalizador no sale de alguna razón, por ejemplo, que bloquea la espera de una condición que no se produce . En este caso, el hilo del finalizador se colgará, por lo que no se acumularán más objetos finalizables . Debe ser muy consciente de esta situación y quedarse con escribiendo el código más simple para liberar sus recursos no administrados en los finalizadores.

Otra consideración es qué sucede durante el cierre de la aplicación. Cuando el programa se cierra , el recolector de basura se esforzará para llamar a los finalizadores de todos los objetos finalizables, pero con ciertas limitaciones :

  • objetos finalizables no se promueven a las generaciones montón más altas durante apagado.

  • Cualquier finalizador individual tendrá un máximo de 2 segundos para ejecutar; si tarda más, será eliminado.

  • Hay un máximo de 40 segundos para todos los finalizadores para ser ejecutados; si algún finalizador se sigue ejecutando, o pendiente en este punto, el proceso completo se cancela abruptamente.

Demasiados mensajes (e incluso la documentación oficial) mal uso del "proceso" y "dominio de la aplicación" términos "aplicación" - la mayoría de ellos aun suponiendo que son iguales, porque por lo general se ejecutan aplicaciones en un único dominio de aplicación en un solo proceso. Este mal uso hace que todos estos documentos sean difíciles de leer, y ni siquiera útiles.

Por lo tanto, mi pregunta asume más de una aplicación, cada una se ejecuta en un dominio de aplicación separado en un solo proceso.

¿Todas estas aplicaciones comparten los mismos subprocesos de GC y finalizador? ¿El problema descrito en el artículo anterior (suspender el hilo del finalizador) afectará a todas las aplicaciones en ese proceso? En caso afirmativo, ¿hay una solución alternativa (además de no utilizar malas aplicaciones), como de alguna manera para descubrir el hilo del finalizador y enviarlo Thread.Abort?

Todo lo anterior es porque me tocó un problema similar. Mi aplicación se ejecuta en un dominio de aplicación separado como complemento de software de terceros (Outlook). Debido a varias razones, necesito llamar a GC.Collect y GC.WaitForPendingFinalizers para liberar completamente las referencias COM (las rutinas de interoperabilidad habituales no son suficientes para Office/Outlook), cuando se está ejecutando un complemento de terceros en particular, mi GC.WaitForPendingFinalizers se cuelga para siempre , entonces sospecho que hay un finalizador "malo" en el agregado de ese tercero. No tengo control sobre la sustitución/eliminación de esa adición (requisito del cliente), así que tengo que resolver por mi cuenta cómo hacer que coexistan.

+0

+1 para una pregunta clara y detallada – Basic

Respuesta

8

Parece que de hecho solo hay un hilo por instancia de CLR dentro del proceso, por el momento, de todos modos. Aquí hay algo de código para demostrar que:

Test.cs:

using System; 

class Test 
{ 
    static void Main() 
    { 
     AppDomain.CreateDomain("First") 
       .ExecuteAssembly("ShowFinalizerThread.exe"); 
     AppDomain.CreateDomain("Second") 
       .ExecuteAssembly("ShowFinalizerThread.exe"); 
    } 
} 

ShowFinalizerThread.cs:

using System; 
using System.Threading; 

class ShowFinalizerThread 
{ 
    static Random rng = new Random(); 

    ~ShowFinalizerThread() 
    { 
     Console.WriteLine("Thread/domain: {0}/{1}", 
          Thread.CurrentThread.ManagedThreadId, 
          AppDomain.CurrentDomain.FriendlyName); 
     if (rng.Next(10) == 0) 
     { 
      Console.WriteLine("Hanging!"); 
      Thread.Sleep(2000); 
     } 
    } 

    static void Main() 
    { 
     new Thread(LoopForever).Start(); 
    } 

    static void LoopForever() 
    { 
     while (true) 
     { 
      new ShowFinalizerThread(); 
      GC.Collect(); 
      GC.WaitForPendingFinalizers(); 
      Thread.Sleep(300); 
     }; 
    } 
} 

compilar cada como una aplicación de consola, a continuación, ejecutar test.exe desde la línea de comandos (es más fácil, IMO). Verás que el finalizador de un dominio de aplicación bloquea a otro.

En el futuro no me sorprendería ver un hilo de finalizador por núcleo en lugar de por dominio de aplicación - pero suena como usted todavía tiene problemas :(

Tienes mi más profunda simpatía (aunque no una solución) - una vez que encontré un punto muerto en un Blob de Oracle. Pudimos arreglarlo disponiéndolo apropiadamente, pero sé que no todo funciona muy bien, ¡y fue realmente doloroso encontrarlo!

+0

Creo que es un hilo por instancia CLR. Comenzando con 2.0 y Silverlight ahora puede tener más de un CLR por proceso. – JaredPar

+0

@JaredPar: tiene razón ... [CLR Inside Out: En proceso, lado a lado] (http://msdn.microsoft.com/en-us/magazine/ee819091.aspx) –

+0

@ JaredPar: editaré. –

Cuestiones relacionadas