Gérer de façon élégante l'annulation de tâches

Lors de l'utilisation de tâches pour les gros/long cours d'exécution des charges de travail que j'ai besoin d'être en mesure de l'annuler, j'utilise souvent un modèle similaire à ce que l'action la tâche s'exécute:

public void DoWork(CancellationToken cancelToken)
{
    try
    {
        //do work
        cancelToken.ThrowIfCancellationRequested();
        //more work
    }
    catch (OperationCanceledException)
    {
        throw;
    }
    catch (Exception ex)
    {
        Log.Exception(ex);
        throw;
    }
}

La OperationCanceledException ne doit pas être enregistré comme une erreur, mais il ne doit pas être avalé si la tâche est de faire la transition vers l'annulation de l'état. Toutes les autres exceptions ne doivent pas être traitées au-delà de la portée de cette méthode.

Ce toujours senti un peu maladroit, et visual studio, par défaut, pause sur le lancer pour OperationCanceledException (Bien que j'ai une pause de l'Utilisateur-non gérée " éteint maintenant pour OperationCanceledException à cause de mon utilisation de ce modèle).

Idéalement, je pense que j'aimerais être capable de faire quelque chose comme ceci:

public void DoWork(CancellationToken cancelToken)
{
    try
    {
        //do work
        cancelToken.ThrowIfCancellationRequested();
        //more work
    }
    catch (Exception ex) exclude (OperationCanceledException)
    {
        Log.Exception(ex);
        throw;
    }
}

c'est à dire avoir une sorte de liste d'exclusion appliquée à la capture, mais sans le support de la langue qui n'est pas possible actuellement (@eric-lippert: c# vNext fonctionnalité :)).

Un autre moyen serait par le biais d'une poursuite:

public void StartWork()
{
    Task.Factory.StartNew(() => DoWork(cancellationSource.Token), cancellationSource.Token)
        .ContinueWith(t => Log.Exception(t.Exception.InnerException), TaskContinuationOptions.OnlyOnFaulted | TaskContinuationOptions.ExecuteSynchronously);
}

public void DoWork(CancellationToken cancelToken)
{
    //do work
    cancelToken.ThrowIfCancellationRequested();
    //more work
}

mais je n'aime pas vraiment que l'exception peut techniquement avoir plus qu'une seule exception interne et vous n'avez pas autant de contexte lors de la connexion de l'exception comme vous le feriez dans le premier exemple (si je faisais plus que juste de l'enregistrement).

Je comprends que c'est un peu une question de style, mais vous vous demandez si quelqu'un a une meilleure suggestion?

Dois-je rester avec l'exemple 1?

Eamon

  • J'utilise une solution où la structure de journalisation faire des choses différentes pour certaines exceptions. c'est à dire ignorer OperationCancelledException, aplatit AggregateException, des journaux uniquement innerException pour InvalidOperationException etc
InformationsquelleAutor Eamon | 2012-09-28