2012-01-12 12 views
10

Sto analizzando alcuni arresti anomali nella mia applicazione causati da un'eccezione Win32 e ho ridotto il limite che deve essere presente nel threadpool che si occupa del gestore di eventi EventLog.EntryWrittenEventHandler nel mio applicazione. Ho impostato questo in questo modo:C# Eccezione di cattura che si sta verificando su ThreadPool

// Create the event log monitor 
eventLog.Log = "Application"; 
eventLog.EnableRaisingEvents = true; 
eventLog.EntryWritten += new EntryWrittenEventHandler(EventLogMonitor); 

EventLogMonitor è il gestore per il mio evento. Mi chiedo se qualcuno abbia qualche idea su dove posso scoprire che cosa sta causando questa eccezione. Sembra che per ascoltare gli eventi sia stato impostato uno ThreadPoolWaitOrTimerCallback, che non avrebbe nessuno del mio codice su di esso, e se l'eccezione si sta verificando su questo non vedo come affrontare questo problema. Qualsiasi aiuto è davvero apprezzato !!

Ecco l'output di clrstack in WinDBG:!

0:008> !clrstack 
OS Thread Id: 0x106c (8) 
ESP  EIP  
049df1c8 7756f871 [HelperMethodFrame: 049df1c8] 
049df26c 73ce6fa0 System.Diagnostics.EventLog.get_OldestEntryNumber() 
049df27c 73bf24ed System.Diagnostics.EventLog.CompletionCallback(System.Object) 
049df2c4 73bf0fe4 System.Diagnostics.EventLog.StaticCompletionCallback(System.Object, Boolean) 
049df2f4 744fc3b8 System.Threading._ThreadPoolWaitOrTimerCallback.WaitOrTimerCallback_Context(System.Object, Boolean) 
049df300 744fc373 System.Threading._ThreadPoolWaitOrTimerCallback.WaitOrTimerCallback_Context_f(System.Object) 
049df304 7400027f System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object) 
049df31c 744fc477 System.Threading._ThreadPoolWaitOrTimerCallback.PerformWaitOrTimerCallback(System.Object, Boolean) 
049df4ac 74991b5c [GCFrame: 049df4ac] 

In caso aiuta, la mia domanda è solo controllando l'ID evento di ogni ingresso scritti nel registro degli eventi, e se corrisponde a uno di un certo set di ID allora lo registro. Gli arresti anomali si verificano raramente e l'eccezione è un'eccezione System.ComponentModel.Win32 con messaggio "Accesso negato". Sembra che potrebbe trattarsi di un problema di autorizzazioni, ma perché funzionerebbe bene per un certo periodo e poi improvvisamente si blocca con questo.

+0

Che tipo di eccezione è vero? –

+0

Eccezione System.ComponentModel.Win32 con messaggio "Accesso negato". La cosa strana è che accade molto raramente, la mia applicazione che funziona come un servizio può andare per giorni e poi improvvisamente si blocca con questo .. – DukeOfMarmalade

+0

È possibile che si stia tentando di creare la propria origine evento, mai utilizzata in precedenza, e che si blocca solo allora? –

risposta

5

Se ho capito bene (sarebbe utile se passi lo stacktrace che ti porta alla conclusione che l'eccezione sta accadendo all'interno di un thread del thread), quindi avvolgi il tuo codice di EventLogMonitor in un blocco try/catch.

Esempio:

void EventLogHandler(object sender, EventArgs args) 
{ 
    try 
    { 
     // Your original code. 
    } 
    catch (Exception ex) 
    { 
     // Log or Write "ex" to the console. Set a breakpoint, whatever. 

     throw; 
    } 
} 

UPDATE: dopo l'aggiornamento sembra come se l'eccezione è infatti non sollevata da dentro il gestore, ma prima si chiama proprio all'interno della classe EventLog.

Si potrebbe provare a registrare un gestore con l'evento AppDomain.UnhandledException e fare la registrazione/gestione in là. Nota che questo non ti permetterà di sopprimere o "cambiare" o avvolgere l'eccezione, ma semplicemente di loggarlo da qualche parte per scopi diagnostici.

Se si desidera controllare l'eccezione una sola volta (o occasionalmente), provare a utilizzare il comando !PrintException dell'estensione SOS in WinDBG.

UPDATE 2: dopo ulteriori indagini trovo piuttosto strano che l'eccezione bolle tutto. Il tuo stacktrace suggerisce che stai usando .NET 3.5 (o precedente, ma non 4) e guardando la classe EventLog in Reflector puoi vedere che l'intera gestione dello , incluso il codice del preambolo che sembra causare l'eccezione, è avvolto in un grosso blocco "try/catch (Exception)/catch". Divertente.

+0

Ho aggiunto l'output di! Clrstack alla mia domanda. Ho effettivamente provato quello che stai suggerendo Christian.K e la mia applicazione si è ancora bloccata senza sparare il try/catch. L'eccezione si verifica in alcuni Threadpool che .NET deve impostare per ascoltare gli eventi scritti di entrata dal registro eventi e le eccezioni non si propagano attraverso i thread quindi non penso che funzionerà. Grazie per il suggerimento però! – DukeOfMarmalade

+0

Grazie per il vostro aiuto su questo problema, Christian.K, non ho ancora capito cosa è successo, ho dovuto passare il problema a Microsoft, ma i vostri suggerimenti hanno aiutato molto a indagare sul problema! – DukeOfMarmalade

+0

Peccato che non siamo riusciti a capirlo completamente. Ho rivisitato il problema, casualmente, un paio di volte, ma non ho trovato nuove idee (il che in realtà non dice molto :-). –

0
  1. Se è possibile, utilizzare Attività in System.Threading.Tasks.
  2. Prova, dove l'azione sta eseguendo ciò che desideri.

    ThreadPool.QueueUserWorkItem(state => 
    { 
        try 
        { 
         action(); 
        } 
        catch (Exception ex) 
        { 
         OnException(ex); 
        } 
    }); 
    
+0

Non penso che funzionerà, quando ti iscrivi al gestore di eventi EventLogEntryWritten un ThreadPool separato sembra essere avviato per monitorare le voci scritte nel registro eventi, è su questo ThreadPool che si verifica l'eccezione. – DukeOfMarmalade

1

Iscriviti a Application.ThreadException nelle vostre Program.cs come segue per essere in grado di catturare le eccezioni che non sono in thread principale.

static void Main() 
    { 
     Application.EnableVisualStyles(); 
     Application.SetCompatibleTextRenderingDefault(false); 
     Application.ThreadException += Application_ThreadException; 
     try 
     { 
      Application.Run(new MainForm()); 
     } 
     catch (Exception e) 
     { 
      HandleException(e); 
     } 
    } 

    static void Application_ThreadException(object sender, System.Threading.ThreadExceptionEventArgs e) 
    { 
     HandleException(e.Exception); 
    } 
+2

+1 per ThreadException! –

0

Non sono sicuro di che tipo di applicazione è, quindi in un caso generale, se hai fortuna, provare agganciando nel dominio di applicazione in cui il codice viene eseguito. Se non si dispone di più domini, si può provare:

AppDomain.CurrentDomain.FirstChanceException += Handler

o

AppDomain.CurrentDomain.UnhandledException += Handler