2011-02-10 15 views
5

Qualcuno può spiegarmi perché non riesco a generare un'eccezione dall'interno dell'AppDomain.Assembly load event? Per esempio:Eccezione da evento AppDomain.AssemblyLoad

class Program 
{ 
    static Program() 
    { 
     AppDomain.CurrentDomain.UnhandledException += (s, a) => 
     { 
      Console.WriteLine("Caught exception!"); 
     }; 

     AppDomain.CurrentDomain.AssemblyLoad += (s, a) => 
     { 
      Console.WriteLine(string.Format("Assembly {0} loaded", a.LoadedAssembly.FullName)); 

      throw new Exception(); 

      Console.WriteLine("Should never get here..."); 
     }; 
    } 

    static void Main(string[] args) 
    { 
     Console.WriteLine(new ClassLibrary1.Class1().TestString()); 
     Console.WriteLine(); 
     Console.WriteLine("Done..."); 
     Console.ReadLine(); 
    } 
} 

Quando eseguo questo, l'uscita è la seguente:

Assembly ClassLibrary1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null loaded 
TestString 
Done... 

Qualcuno può spiegare questo comportamento a me? Grazie.

EDIT Per chiarire un paio di cose:

  • L'evento carico di montaggio funziona bene, quando mi aspetto che venga eseguito. Ma la mia eccezione non viene mai lanciata

  • Questo è un esempio distillato preso da un'applicazione più grande. Voglio ispezionare il montaggio dopo che è stato caricato e se non mi piace qualcosa, io voglio fallire in fretta ... Ma la mia eccezione non fa 'capita'

+0

stai eseguendo su una macchina a 64 bit? ho avuto un simil ar problema. Vedi: http://stackoverflow.com/questions/4125876/what-happens-when-you-attempt-to-access-a-winforms-treeview-by-keyword-and-that-k/4125994#4125994 – Crisfole

+0

@Cpfohl : Grazie, sono su x64 ma il mio target di piattaforma è già x86 ... – TheNextman

+0

In realtà questo ha senso comunque, poiché l'errore è per il caricamento dei moduli, non per il caricamento generale. – Crisfole

risposta

1

Perché pensi che l'eccezione Se non venisse lanciata, ci si aspetterebbe di vedere l'output "Non dovrebbe mai arrivare qui ..." Tuttavia, poiché non è lì, presumibilmente viene lanciata l'eccezione

Il tuo codice non cattura l'eccezione è tutta un'altra storia. E 'del tutto possibile che il codice che genera l'evento AppDomain.AssemblyLoad è la cattura delle eccezioni.

+0

Sì, hai ragione: ovviamente la mia eccezione veniva lanciata (in base alla seconda Console.WriteLine che non era in esecuzione). Sembra che qualcuno più in alto stia gestendo l'eccezione. – TheNextman

+0

Quindi la prossima domanda logica è perché viene catturato? Microsoft ha una posizione molto forte nel garantire che le eccezioni si propagano sempre nei loro BCL se non gestite. – Tyson

+0

@Tyson: l'eccezione sembra essere consumata dal CLR, non dal BCL. Per quanto riguarda il motivo per cui viene catturato, non sono a conoscenza di alcuna documentazione che risolva questo problema in alcun modo. –

1

Questo accade a causa della il modo in cui funziona il compilatore JIT. È necessario generare il codice per il metodo Main() prima che possa iniziare a funzionare. Poiché si fa riferimento al tipo ClassLibrary1.Class1(), è necessario caricare tale assembly per recuperare le informazioni sul tipo. Ciò richiede il caricamento del gruppo prima del in cui il codice viene avviato. Modificare in questo modo di ottenere l'eccezione:

using System.Runtime.CompilerServices; 
... 
    static void Main(string[] args) { 
     Test(); 
    } 
    [MethodImpl(MethodImplOptions.NoInlining)] 
    static void Test() { 
     Console.WriteLine(new ClassLibrary1.Class1().TestString()); 
     Console.WriteLine(); 
     Console.WriteLine("Done..."); 
     Console.ReadLine(); 
    } 

Ora il costruttore statico può essere eseguito prima e registrare il gestore di eventi AssemblyLoad davanti all'assemblea ClassLibrary1 viene caricato.

+0

Grazie, ma questo non sembra funzionare ... Il risultato è lo stesso. – TheNextman

0

Credo che l'evento di caricamento dell'assieme stia accadendo su un thread separato, utilizzando asynccallback. Non si ottiene l'eccezione perché è necessario utilizzare Application.ThreadException + = new System.Threading.ThreadExceptionEventHandler (Application_ThreadException);

penso, io non sono un esperto di questo a tutti

1

viene generata l'eccezione. Ma sembra che a volte Net ignori le eccezioni che si verificano all'avvio (Main()). Non sono sicuro del motivo, ma di solito vado a Debug-> Eccezioni e spunta la casella "Getta" per Common Language Runtime Exceptions "per essere in grado di interrompere l'eccezione

+0

Sì, hai ragione.L'eccezione viene lanciata assumendo che io abbia permesso a VS di rompere le eccezioni generate ... Ma l'esecuzione continua comunque. – TheNextman

Problemi correlati