Je peux me connecter à AppDomain.CurrentDomain.UnhandledException
pour consigner des exceptions provenant de threads d'arrière-plan, mais comment puis-je les empêcher de mettre fin à l'exécution?
Réponses
Trop de publicités?De Joe Albahari excellent filetage de l'article:
L' .NET framework fournit un niveau inférieur événement global d'exception manipulation: Domaine d'application.UnhandledException. Cette l'événement se déclenche lorsqu'il y a un non gérée exception dans n'importe quel thread, et en tout type de la demande (avec ou sans interface utilisateur). Cependant, alors qu'il offre un bon dispositif de dernier recours pour l'exploitation forestière non interceptée exceptions, il ne fournit aucun moyen de prévention de la demande d'arrêter et de aucun moyen de réprimer l' .NET exception non gérée boîte de dialogue.
Dans les applications de production, explicite la gestion des exceptions est requis sur toutes les fil de méthodes d'entrée. On peut couper la de travail par l'utilisation d'un wrapper ou d'aide classe pour effectuer le travail, comme BackgroundWorker (discuté dans la Partie 3).
En gardant la réponse courte, oui, vous pouvez empêcher le runtime de se terminer.
Voici une démonstration de la solution de contournement:
class Program
{
void Run()
{
AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);
Console.WriteLine("Press enter to exit.");
do
{
(new Thread(delegate()
{
throw new ArgumentException("ha-ha");
})).Start();
} while (Console.ReadLine().Trim().ToLowerInvariant() == "x");
Console.WriteLine("last good-bye");
}
int r = 0;
void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
Interlocked.Increment(ref r);
Console.WriteLine("handled. {0}", r);
Console.WriteLine("Terminating " + e.IsTerminating.ToString());
Thread.CurrentThread.IsBackground = true;
Thread.CurrentThread.Name = "Dead thread";
while (true)
Thread.Sleep(TimeSpan.FromHours(1));
//Process.GetCurrentProcess().Kill();
}
static void Main(string[] args)
{
Console.WriteLine("...");
(new Program()).Run();
}
}
En gros, vous n'avez pas laissé le moteur d'exécution afficher la boîte de dialogue "... le programme a cessé de fonctionner".
Au cas où vous auriez besoin de consigner l'exception et de quitter silencieusement , vous pouvez appeler Process.GetCurrentProcess().Kill();
Voici un excellent article de blog sur ce problème: Gestion des "exceptions non gérées" dans .NET 2.0
OMI, il serait juste de gérer manuellement les exceptions dans les threads d'arrière-plan et de les renvoyer via callback si nécessaire.
delegate void ExceptionCallback(Exception ex);
void MyExceptionCallback(Exception ex)
{
throw ex; // Handle/re-throw if necessary
}
void BackgroundThreadProc(Object obj)
{
try
{
throw new Exception();
}
catch (Exception ex)
{
this.BeginInvoke(new ExceptionCallback(MyExceptionCallback), ex);
}
}
private void Test()
{
ThreadPool.QueueUserWorkItem(new WaitCallback(BackgroundThreadProc));
}