Sulla base della mia ricerca, ho imparato quanto segue:TaskScheduler.UnobservedTaskException non viene mai chiamato
TaskScheduler.UnobservedTaskException
deve attendere che il compito da garbage collection prima eccezione inosservato quel compito sarà bolla fino alla manifestazioneUnobservedTaskException
.- Se si utilizza
Task.Wait()
, non verrà mai richiamato comunque, perché si sta bloccando un risultato imminente dall'attività, quindi l'eccezione verrà generata suTask.Wait()
invece che bolla fino all'eventoUnobservedException
. - Chiamare il numero
GC.Collect()
manualmente è in genere una cattiva idea, a meno che non si sappia esattamente cosa si sta facendo, quindi è utile in questo caso per confermare le cose, ma non come una soluzione adeguata al problema.
Il problema
Se le mie uscite di applicazione prima che il garbage collector entra in gioco, sono assolutamente al 100% non possono ottenere il mio caso UnobservedTaskException
al fuoco.
Nota il seguente codice:
class Program
{
static void Main(string[] args)
{
TaskScheduler.UnobservedTaskException += TaskScheduler_UnobservedTaskException;
Task.Factory.StartNew(() =>
{
Console.WriteLine("Task started.");
throw new Exception("Test Exception");
});
Thread.Sleep(1000);
//GC.Collect();
//GC.WaitForPendingFinalizers();
}
static void TaskScheduler_UnobservedTaskException(object sender, UnobservedTaskExceptionEventArgs e)
{
File.WriteAllText(@"C:\data\TestException.txt", e.Exception.ToString());
Console.WriteLine("EXCEPTION UNOBSERVED");
}
}
Nessun eccezione è scritto e nulla è scritto nella console. 10-15 minuti e più possono passare dopo che l'applicazione è terminata e ancora non vedo alcuna prova che i resti della mia applicazione siano stati raccolti. Potresti chiedere, beh, perché non raccoglierti solo all'uscita? Bene, il mio scenario del mondo reale è che il mio trapping di eccezione viene eseguito all'interno di un servizio WCF ospitato all'interno di un servizio di Windows, ovvero . Non riesco a intercettarlo quando il servizio di Windows si sta spegnendo (e quindi manualmente chiama GC.Collect()
) perché non c'è nessun evento per quello che posso vedere.
Dove sto andando male? Come faccio a garantire che se qualcosa in profondità all'interno del servizio WCF interrompe in definitiva il servizio Windows, ho la possibilità di registrare l'eccezione prima che il servizio cada?
Ciao, grazie per il suggerimento, anche se in realtà lo sto già eseguendo all'esterno del debugger.Noto anche che stai usando GC.Collect(). Cosa succede nel tuo esempio se non raccogli manualmente? –
@Nathan: Normalmente, non c'è abbastanza pressione GC per fare in modo che ciò accada in questo semplice esempio. Se il GC non si accumula, il "task" non colpirà il finalizzatore e l'UnobservedException non si attiva mai. Succede solo quando il finalizzatore raccoglie un'attività senza root con un'eccezione. –
@Nathan: si noti che UnobservedTaskException non impedirà l'arresto della app in ogni caso: è necessario gestire le eccezioni all'interno dell'attività o attendere sempre un'attività, se si desidera impedire l'arresto di un'app. –