42 votes

Comment gérer toutes les exceptions non gérées lors de l'utilisation de la bibliothèque parallèle de tâches?

Je suis à l'aide de la TPL (Task Parallel Library) dans .NET 4.0. Je veux être capable de centraliser la logique de traitement de toutes les exceptions non gérées par l'aide de la Thread.GetDomain().UnhandledException événement. Cependant, dans mon application, l'événement n'est jamais tiré de threads a commencé avec TPL code, par exemple, Task.Factory.StartNew(...). L'événement est en effet tiré si j'utilise quelque chose comme new Thread(threadStart).Start().

Cet article MSDN suggère d'utiliser Tâche#Wait() pour attraper l' AggregateException lorsque l'on travaille avec TPL, mais ce n'est pas que je veux parce qu'il n'est pas "centralisé" assez d'un mécanisme.

Personne ne l'expérience même problème ou est-ce juste moi? Avez-vous une solution pour cela?

35voto

Sergey Teplyakov Points 6556

Je pense que TaskScheduler.UnobservedTaskException Événement est ce que vous voulez:

Se produit lorsqu'un reproché à la Tâche inaperçu exception est sur le point de déclencher exception escalade de la politique, qui, par défaut, peut mettre fin à l' processus.

Donc, cet événement est similaire à l' DomainUnhandledException que vous avez mentionné dans votre question, mais ne se produit que pour les tâches.

BTW remarque, que non-exceptions de la politique (oui, ce n'est pas une surprise exceptions, MS gars a inventé un nouveau mot ... une fois de plus), changé depuis .NET 4.0 .NET 4.5. Dans .NET 4.0 inaperçu exception conduit à l'arrêt du processus mais dans .NET 4.5 - ne. Tout cela parce que de nouveaux async choses que nous aurons dans C# 5 et VB 11.

21voto

Buu Nguyen Points 19391

Semble comme il n'y a pas intégré dans la façon de gérer cela (et pas de réponse à cette question après presque 2 semaines). J'ai déjà roulé quelques code personnalisé pour prendre soin de cela. La description de la solution est assez long, donc je l'ai posté dans mon blog. Reportez-vous à ce post si vous êtes intéressé.

Mise à jour 5/7/2010: j'ai trouvé une meilleure façon de le faire, l'utilisation de la tâche de poursuite. J'ai créer un class ThreadFactory qui expose l'événement d'Erreur qui peut être souscrit par un haut-gestionnaire de niveau et fournit des méthodes pour démarrer une tâche attaché avec une bonne continuation.
Le code est disponible ici.

Mise à jour 4/18/2011: code postal dans le blog en tant que par Nifle commentaire.

internal class ThreadFactory
{
    public delegate void TaskError(Task task, Exception error);

    public static readonly ThreadFactory Instance = new ThreadFactory();

    private ThreadFactory() {}

    public event TaskError Error;

    public void InvokeError(Task task, Exception error)
    {
        TaskError handler = Error;
        if (handler != null) handler(task, error);
    }

    public void Start(Action action)
    {
        var task = new Task(action);
        Start(task);
    }

    public void Start(Action action, TaskCreationOptions options)
    {
        var task = new Task(action, options);
        Start(task);
    }

    private void Start(Task task)
    {
        task.ContinueWith(t => InvokeError(t, t.Exception.InnerException),
                            TaskContinuationOptions.OnlyOnFaulted |
                            TaskContinuationOptions.ExecuteSynchronously);
        task.Start();
    }
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X