Question

J'utilise le TPL ( Bibliothèque parallèle de tâches ) dans .NET 4.0. Je veux centraliser la logique de gestion de toutes les exceptions non gérées en utilisant l'événement Thread.GetDomain().UnhandledException. Cependant, dans ma demande, l'événement est jamais déclenché pour les discussions ouvertes avec le code TPL, par exemple Task.Factory.StartNew(...). L'événement est en effet tiré si j'utiliser quelque chose comme new Thread(threadStart).Start().

Cet article MSDN suggère d'utiliser Task.Wait () pour attraper le AggregateException lorsque vous travaillez avec TPL, mais ce n'est pas ce que je veux parce que ce mécanisme ne suffit pas « centralisé ».

Est-ce que quelqu'un l'expérience même problème du tout ou est-ce juste moi? Avez-vous une solution pour cela?

Était-ce utile?

La solution 2

On dirait qu'il n'y a pas moyen de gérer intégré ce (et pas de réponse à cette question après presque 2 semaines). Je l'ai déjà déployé un code personnalisé pour prendre soin de cela. La description de la solution est assez longue, donc je l'ai signalé dans mon blog. Reportez-vous à ce message si vous êtes intéressé.

Mise à jour 5/7/2010: Je l'ai trouvé une meilleure façon de le faire, faisant usage de la poursuite des tâches. Je crée un class ThreadFactory qui expose l'événement d'erreur qui peut être souscrite par un gestionnaire de niveau supérieur et fournit des méthodes pour commencer une tâche attachée avec une bonne continuation.
Le code est affiché ici .

Mise à jour 4/18/2011:. Code postal du blog selon le commentaire de Nifle

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();
    }
}

Autres conseils

Je vois deux options qui peuvent être utilisées aux fins de la centralisation de la gestion des exceptions dans TPL:   1. À l'aide de inobservée événement d'exception Tâche du Planificateur de tâches.   2. Utilisation de continuations pour des tâches avec l'état faillé.

Utilisation de inobservée événement d'exception Tâche du Planificateur de tâches.

Le planificateur de tâches a un événement UnobservedTaskException auquel vous pouvez vous abonner en utilisant l'opérateur + =.

  • Note 1: Dans le corps du gestionnaire que vous devez faire appel SetObserved () sur l'argument UnobservedTaskExceptionEventArgs pour notifier ordonnanceur cette exception a été traitée
  • .
  • Note 2:. Le gestionnaire est appelé lorsque les tâches ont été collectées par le collecteur des ordures
  • Note 3:. Si vous attendrez la tâche vous sera toujours obligé d'attendre protégiez en bloc try / catch
  • Note 4:. La politique par défaut des exceptions Tâche non gérée dans .Net 4.0 et 4.5 est différent

Résumé:. Cette approche est bonne pour les tâches et oublier le feu et saisie d'une exception échappé de votre politique de traitement d'exception centralisée

Utilisation des continuations pour des tâches avec l'état faillé.

Avec TPL vous pouvez joindre des actions à l'aide de la méthode de travail ContinueWith () qui prend attache option d'action et poursuite. Cette action sera appelée après la fin de la tâche et que dans les cas spécifiés par l'option. En particulier:

    t.ContinueWith(c => { /* exception handling code */ },
                   TaskContinuationOptions.OnlyOnFaulted);

installe suite avec le code de gestion des exceptions au t Tâche. Ce code sera en cours d'exécution que dans le cas où la tâche t a pris fin en raison de l'exception non gérée.

  • Note 1: Obtenir la valeur d'exception dans le code de gestion des exceptions. Sinon, il sera barboter dehors.
  • Note 2:. Exception code de gestion sera appelé immédiatement après la fin des tâches
  • Note 3: Si l'exception a été obtenu dans le code de gestion des exceptions, il sera considéré comme manipulé, bloc try / catch sur l'attente de la tâche ne sera pas en mesure de l'attraper.

Je pense que ce sera mieux pour exception centralisée la manipulation à utiliser des tâches personnalisées héritées de la tâche avec gestionnaire d'exception ajouté par suite. Et accompagner cette approche à l'aide de inobservée événement d'exception Tâche du Planificateur de tâches à des tentatives de capture d'utiliser des tâches non personnalisées.

scroll top