Exceptions Windows Workflow Foundation

Les flux de travail peuvent utiliser l'activité TryCatch pour gérer des exceptions déclenchées lors de leur exécution. Ces exceptions peuvent être gérées ou être à nouveau levées à l'aide de l'activité Rethrow. Les activités de la section Finally sont exécutées lorsque soit la section Try, soit la section Catches est terminée. Les workflows hébergés par une instance WorkflowApplication peuvent également utiliser le gestionnaire d’événements OnUnhandledException pour gérer des exceptions non prises en charge par une activité TryCatch.

Raisons des exceptions

Dans un workflow, les exceptions peuvent être générées des différentes manières suivantes :

  • délai d'expiration de transactions dans l'objet TransactionScope ;

  • exception explicite levée par le flux de travail à l'aide de l'activité Throw ;

  • exception .NET Framework 4.6.1 levée depuis une activité ;

  • exception levée par un code externe, tel que les bibliothèques, composants ou services utilisés dans le flux de travail.

Gestion des exceptions

Si une exception est levée par une activité et n'est pas gérée, le comportement par défaut consiste à arrêter l'instance de flux de travail. En cas de présence d'un gestionnaire OnUnhandledException personnalisé, il peut substituer ce comportement par défaut. Ce gestionnaire permet à l’auteur hôte du workflow de fournir la gestion appropriée, englobant par exemple l’enregistrement personnalisé, l’abandon de workflow, l’annulation de workflow ou l’arrêt de workflow. Si un workflow lève une exception qui n'est pas gérée, le gestionnaire OnUnhandledException est appelé. Il existe trois actions possibles retournées depuis OnUnhandledException qui déterminent les résultats finaux du flux de travail.

  • Annulation - Une instance annulée de flux de travail est une sortie normale d’une exécution de branche. Vous pouvez modéliser le comportement d’annulation (par exemple, en utilisant une activité CancellationScope). Le gestionnaire Completed est appelé lorsque le processus d'annulation se termine. Un flux de travail annulé est dans un état d'annulation.

  • Terminate - Une instance de flux de travail terminée ne peut pas être reprise ou redémarrée. Cela déclenche l'événement Completed dans lequel vous pouvez fournir une exception comme la raison de l'arrêt. Le gestionnaire Terminated est appelé lorsque le processus d'arrêt se termine. Un flux de travail terminé est dans l'état d'erreur.

  • Abandon - Une instance de flux de travail abandonnée peut reprendre uniquement si elle a été configurée pour être persistante. Sans persistance, un flux de travail ne peut pas être repris. Au stade où un flux de travail est abandonné, les tâches effectuées (en mémoire) depuis le dernier point de persistance sont perdues. Pour un workflow abandonné, le gestionnaire Aborted est appelé en utilisant l'exception comme raison lorsque le processus d'abandon est terminé. Toutefois, contrairement aux gestionnaires Cancelled et Terminated, le gestionnaire Completed n'est pas appelé. Un flux de travail abandonné est dans un état d'abandon.

L'exemple suivant appelle un workflow qui lève une exception. L'exception n'est pas prise en charge par le workflow et le gestionnaire OnUnhandledException est appelé. L'objet WorkflowApplicationUnhandledExceptionEventArgs est inspecté de façon à fournir des informations sur l'exception, et le workflow est arrêté.

Activity wf = new Sequence
{
    Activities =
     {
         new WriteLine
         {
             Text = "Starting the workflow."
         },
         new Throw
        {
            Exception = new InArgument<Exception>((env) =>
                new ApplicationException("Something unexpected happened."))
        },
        new WriteLine
         {
             Text = "Ending the workflow."
         }
     }
};

WorkflowApplication wfApp = new WorkflowApplication(wf);

wfApp.OnUnhandledException = delegate (WorkflowApplicationUnhandledExceptionEventArgs e)
{
    // Display the unhandled exception.
    Console.WriteLine("OnUnhandledException in Workflow {0}\n{1}",
        e.InstanceId, e.UnhandledException.Message);

    Console.WriteLine("ExceptionSource: {0} - {1}",
        e.ExceptionSource.DisplayName, e.ExceptionSourceInstanceId);

    // Instruct the runtime to terminate the workflow.
    return UnhandledExceptionAction.Terminate;

    // Other choices are UnhandledExceptionAction.Abort and
    // UnhandledExceptionAction.Cancel
};

wfApp.Run();

Gestion des exceptions avec l'activité TryCatch

La gestion des exceptions au sein d'un workflow est effectuée avec l'activité TryCatch. L’activité TryCatch possède une collection Catches des activités Catch qui sont toutes associées à un type Exception spécifique. Si l'exception levée par une activité contenue dans la section Try d'une activité TryCatch correspond à l'exception d'une activité Catch<TException> dans la collection Catches, elle est gérée. L'exception passe à l'activité parente si elle est explicitement à nouveau levée ou si une nouvelle exception est levée. L'exemple de code suivant illustre une activité TryCatch qui gère un objet ApplicationException levé dans la section Try par une activité Throw. Le message de l'exception est écrit sur la console par l'activité Catch<TException>, puis un message est écrit sur la console dans la section Finally.

DelegateInArgument<ApplicationException> ex = new DelegateInArgument<ApplicationException>()
{
    Name = "ex"
};

Activity wf = new TryCatch
{
    Try = new Throw()
    {
        Exception = new InArgument<Exception>((env) => new ApplicationException("An ApplicationException was thrown."))
    },
    Catches =
    {
        new Catch<ApplicationException>
        {
            Action = new ActivityAction<ApplicationException>
            {
                Argument = ex,
                Handler = new WriteLine()
                {
                    Text = new InArgument<string>((env) => ex.Get(env).Message)
                }
            }
        }
    },
    Finally = new WriteLine()
    {
        Text = "Executing in Finally."
    }
};

Les activités dans la section Finally sont exécutées lorsque soit la section Try, soit la section Catches est terminée correctement. La section Try se termine correctement si aucune exception n'est levée, et la section Catches se termine correctement si aucune exception n'est levée ou à nouveau levée. Si une exception est levée dans la section Try d'un TryCatch et n'est pas gérée par Catch<TException> dans la section Catches, ou est à nouveau levée dans Catches, les activités dans Finally ne seront pas exécutées à moins qu'une des opérations suivantes se produise.

Gestion des exceptions et compensation

La différence entre la gestion des exceptions et la compensation réside dans le fait que la gestion des exceptions a lieu lors de l'exécution d'une activité. La compensation a lieu une fois une activité terminée correctement. La gestion des exceptions permet de nettoyer une fois l'exception levée par l'activité, tandis que la compensation fournit un mécanisme permettant d'annuler un travail correctement terminé d'une activité précédemment terminée. Pour plus d’informations, consultez Compensation.

Voir aussi