Procédure : exécuter un workflow

Cette rubrique est la suite du didacticiel de mise en route de Windows Workflow Foundation et explique comment créer un hôte de workflow et exécuter le workflow défini dans la rubrique précédente How to: Create a Workflow .

Notes

Chaque rubrique du didacticiel de mise en route dépend des rubriques précédentes. Avant de parcourir cette rubrique, vous devez avoir parcouru How to: Create an Activity et How to: Create a Workflow.

Pour créer le projet d'hôte du workflow

  1. Ouvrez la solution de la rubrique précédente Comment créer une activité en utilisant Visual Studio 2012.

  2. Dans l' Explorateur de solutions , cliquez avec le bouton droit sur la solution WF45GettingStartedTutorial , puis sélectionnez Ajouter, Nouveau projet.

    Conseil

    Si la fenêtre Explorateur de solutions ne s'affiche pas, sélectionnez Explorateur de solutions dans le menu Afficher.

  3. Dans le nœud Installé , sélectionnez Visual C#, Workflow (ou Visual Basic, Workflow).

    Notes

    Selon le langage de programmation configuré comme langage principal dans Visual Studio, le nœud Visual C# ou Visual Basic peut se trouver sous le nœud Autres langages dans le nœud Installé.

    Assurez-vous que .NET Framework 4.5 est sélectionné dans la liste déroulante de la version .NET Framework. Dans la liste Workflow , sélectionnez Application console de workflow . Dans la zone NumberGuessWorkflowHost Nom , tapez et cliquez sur OK. Une application de workflow de démarrage est ainsi créée, ainsi qu'un support d'hébergement de workflow de base. Le code d'hébergement de base est modifié et sert à exécuter l'application de workflow.

  4. Cliquez avec le bouton droit sur le projet NumberGuessWorkflowHost récemment ajouté dans l' Explorateur de solutions , puis sélectionnez Ajouter une référence. Dans la liste Ajouter une référence , sélectionnez Solution , activez la case à cocher en regard de NumberGuessWorkflowActivities, puis cliquez sur OK.

  5. Cliquez avec le bouton droit sur Workflow1.xaml dans l' Explorateur de solutions et choisissez Supprimer. Cliquez sur OK pour confirmer.

Pour modifier le code d'hébergement de workflow

  1. Double-cliquez sur Program.cs ou sur Module1.vb dans l' Explorateur de solutions pour afficher le code.

    Conseil

    Si la fenêtre Explorateur de solutions ne s'affiche pas, sélectionnez Explorateur de solutions dans le menu Afficher.

    Étant donné que ce projet a été créé à l'aide du modèle Application console de workflow , Program.cs ou Module1.vb contient le code d'hébergement de workflow de base suivant.

    ' Create and cache the workflow definition.
    Dim workflow1 As Activity = New Workflow1()
    WorkflowInvoker.Invoke(workflow1)
    
    // Create and cache the workflow definition.
    Activity workflow1 = new Workflow1();
    WorkflowInvoker.Invoke(workflow1);
    

    Ce code d'hébergement généré utilise WorkflowInvoker. WorkflowInvoker offre un moyen simple pour appeler un workflow comme s'il s'agissait d'un appel de méthode et ne peut être utilisé que pour les workflows qui n'utilisent pas la persistance. WorkflowApplication fournit un modèle plus riche pour exécuter des workflows, qui inclut la notification des événements de cycle de vie, le contrôle d'exécution, la modification de signet et la persistance. Cet exemple utilise des signets et WorkflowApplication est utilisé pour l'hébergement du workflow. Ajoutez l'instruction using ou Imports suivante dans la partie supérieure de Program.cs ou Module1.vb sous les instructions using ou Imports existantes.

    Imports NumberGuessWorkflowActivities
    Imports System.Threading
    
    using NumberGuessWorkflowActivities;
    using System.Threading;
    

    Remplacez les lignes de code qui utilisent WorkflowInvoker par le code d'hébergement WorkflowApplication de base suivant. Cet exemple de code d'hébergement montre les étapes de base pour l'hébergement et l'appel d'un workflow, mais ne contient pas encore les fonctionnalités pour exécuter avec succès le workflow à partir de cette rubrique. Au cours des étapes suivantes, le code de base est modifié et des fonctionnalités supplémentaires sont ajoutées jusqu'à ce que l'application soit terminée.

    Notes

    Remplacez Workflow1 dans ces exemples par FlowchartNumberGuessWorkflow, SequentialNumberGuessWorkflowou StateMachineNumberGuessWorkflow, en fonction du workflow que vous avez effectué à l’étape précédente How to: Create a Workflow . Si vous ne substituez pas Workflow1 , vous obtiendrez des erreurs de build lors de la génération ou de l'exécution du workflow.

    AutoResetEvent syncEvent = new AutoResetEvent(false);
    
    WorkflowApplication wfApp =
        new WorkflowApplication(new Workflow1());
    
    wfApp.Completed = delegate (WorkflowApplicationCompletedEventArgs e)
    {
        syncEvent.Set();
    };
    
    wfApp.Aborted = delegate (WorkflowApplicationAbortedEventArgs e)
    {
        Console.WriteLine(e.Reason);
        syncEvent.Set();
    };
    
    wfApp.OnUnhandledException = delegate (WorkflowApplicationUnhandledExceptionEventArgs e)
    {
        Console.WriteLine(e.UnhandledException.ToString());
        return UnhandledExceptionAction.Terminate;
    };
    
    wfApp.Run();
    
    syncEvent.WaitOne();
    
    Dim syncEvent As New AutoResetEvent(False)
    
    Dim wfApp As New WorkflowApplication(New Workflow1())
    
    wfApp.Completed = _
        Sub(e As WorkflowApplicationCompletedEventArgs)
            syncEvent.Set()
        End Sub
    
    wfApp.Aborted = _
        Sub(e As WorkflowApplicationAbortedEventArgs)
            Console.WriteLine(e.Reason)
            syncEvent.Set()
        End Sub
    
    wfApp.OnUnhandledException = _
        Function(e As WorkflowApplicationUnhandledExceptionEventArgs)
            Console.WriteLine(e.UnhandledException)
            Return UnhandledExceptionAction.Terminate
        End Function
    
    wfApp.Run()
    
    syncEvent.WaitOne()
    

    Ce code crée un WorkflowApplication, s'abonne à trois événements de cycle de vie du workflow, démarre le workflow avec un appel à la méthode Run, puis attend que le workflow soit terminé. Lorsque le workflow est terminé, le AutoResetEvent est défini et l'application hôte se termine.

Pour définir des arguments d'entrée d'un workflow

  1. Ajoutez l'instruction suivante dans la partie supérieure de Program.cs ou Module1.vb sous les instructions using ou Imports existantes.

    using System.Collections.Generic;
    using System.Threading;
    
    Imports System.Collections.Generic
    
  2. Remplacez la ligne de code qui crée le WorkflowApplication par le code suivant qui crée et passe un dictionnaire de paramètres au workflow lorsqu'il est créé.

    Notes

    Remplacez Workflow1 dans ces exemples par FlowchartNumberGuessWorkflow, SequentialNumberGuessWorkflowou StateMachineNumberGuessWorkflow, en fonction du workflow que vous avez effectué à l’étape précédente How to: Create a Workflow . Si vous ne substituez pas Workflow1 , vous obtiendrez des erreurs de build lors de la génération ou de l'exécution du workflow.

    var inputs = new Dictionary<string, object>() { { "MaxNumber", 100 } };
    
    WorkflowApplication wfApp =
        new WorkflowApplication(new Workflow1(), inputs);
    
    Dim inputs As New Dictionary(Of String, Object)
    inputs.Add("MaxNumber", 100)
    
    Dim wfApp As New WorkflowApplication(New Workflow1(), inputs)
    

    Ce dictionnaire contient un élément avec une clé de MaxNumber. Les clés du dictionnaire d'entrée correspondent aux arguments d'entrée sur l'activité racine du workflow. MaxNumber est utilisé par le workflow pour déterminer la limite supérieure pour le nombre généré de manière aléatoire.

Pour récupérer des arguments de sortie d'un workflow

  1. Modifiez le gestionnaire Completed pour récupérer et afficher le nombre de tours utilisé par le workflow.

    wfApp.Completed = delegate (WorkflowApplicationCompletedEventArgs e)
    {
        int Turns = Convert.ToInt32(e.Outputs["Turns"]);
        Console.WriteLine("Congratulations, you guessed the number in {0} turns.", Turns);
    
        syncEvent.Set();
    };
    
    wfApp.Completed = _
        Sub(e As WorkflowApplicationCompletedEventArgs)
            Dim Turns As Integer = Convert.ToInt32(e.Outputs("Turns"))
            Console.WriteLine("Congratulations, you guessed the number in {0} turns.", Turns)
    
            syncEvent.Set()
        End Sub
    

Pour reprendre un signet

  1. Ajoutez le code suivant en haut de la méthode Main , juste après la déclaration AutoResetEvent existante.

    AutoResetEvent idleEvent = new AutoResetEvent(false);
    
    Dim idleEvent As New AutoResetEvent(False)
    
  2. Ajoutez le gestionnaire Idle suivant, juste en dessous des trois gestionnaires de cycle de vie du workflow existants dans Main.

    wfApp.Idle = delegate (WorkflowApplicationIdleEventArgs e)
    {
        idleEvent.Set();
    };
    
    wfApp.Idle = _
        Sub(e As WorkflowApplicationIdleEventArgs)
            idleEvent.Set()
        End Sub
    

    Chaque fois que le workflow est inactif dans l’attente de l’estimation suivante, ce gestionnaire est appelé et le idleActionAutoResetEvent est défini. Le code de l'étape suivante utilise idleEvent et syncEvent pour déterminer si le workflow attend l'estimation suivante ou s'il est terminé.

    Notes

    Dans cet exemple, l'application hôte utilise des événements à réinitialisation automatique dans les gestionnaires Completed et Idle pour synchroniser l'application hôte avec la progression du workflow. Il n'est pas nécessaire de bloquer et d'attendre que le workflow devienne inactif avant de reprendre un signet mais, dans cet exemple, les événements de synchronisation sont nécessaires afin que l'hôte sache si le workflow est terminé ou s'il attend une ou plusieurs autres entrées d'utilisateur à l'aide de Bookmark. Pour plus d’informations, consultez Signets.

  3. Supprimez l'appel à WaitOneet remplacez-le par du code pour recueillir l'entrée de l'utilisateur et reprendre le Bookmark.

    Supprimez la ligne de code suivante.

    syncEvent.WaitOne();
    
    syncEvent.WaitOne()
    

    Remplacez-la par l'exemple suivant.

    // Loop until the workflow completes.
    WaitHandle[] handles = new WaitHandle[] { syncEvent, idleEvent };
    while (WaitHandle.WaitAny(handles) != 0)
    {
        // Gather the user input and resume the bookmark.
        bool validEntry = false;
        while (!validEntry)
        {
            int Guess;
            if (!Int32.TryParse(Console.ReadLine(), out Guess))
            {
                Console.WriteLine("Please enter an integer.");
            }
            else
            {
                validEntry = true;
                wfApp.ResumeBookmark("EnterGuess", Guess);
            }
        }
    }
    
    ' Loop until the workflow completes.
    Dim waitHandles As WaitHandle() = New WaitHandle() {syncEvent, idleEvent}
    Do While WaitHandle.WaitAny(waitHandles) <> 0
        'Gather the user input and resume the bookmark.
        Dim validEntry As Boolean = False
        Do While validEntry = False
            Dim Guess As Integer
            If Int32.TryParse(Console.ReadLine(), Guess) = False Then
                Console.WriteLine("Please enter an integer.")
            Else
                validEntry = True
                wfApp.ResumeBookmark("EnterGuess", Guess)
            End If
        Loop
    Loop
    

Pour générer et exécuter l'application

  1. Cliquez avec le bouton droit sur NumberGuessWorkflowHost dans l' Explorateur de solutions , puis sélectionnez Définir comme projet de démarrage.

  2. Appuyez sur Ctrl+F5 pour générer et exécuter l'application. Essayez de deviner le nombre en aussi peu de tours que possible.

    Pour essayer l'application avec un des autres styles de workflow, remplacez Workflow1 dans le code qui crée le WorkflowApplication par FlowchartNumberGuessWorkflow, SequentialNumberGuessWorkflow, ou StateMachineNumberGuessWorkflow, en fonction du style de workflow souhaité.

    var inputs = new Dictionary<string, object>() { { "MaxNumber", 100 } };
    
    WorkflowApplication wfApp =
        new WorkflowApplication(new Workflow1(), inputs);
    
    Dim inputs As New Dictionary(Of String, Object)
    inputs.Add("MaxNumber", 100)
    
    Dim wfApp As New WorkflowApplication(New Workflow1(), inputs)
    

    Pour obtenir des instructions sur la façon d’ajouter la persistance à une application de workflow, consultez la rubrique suivante, How to: Create and Run a Long Running Workflow.

Exemple

L'exemple suivant constitue l'intégralité du code de la méthode Main .

Notes

Remplacez Workflow1 dans ces exemples par FlowchartNumberGuessWorkflow, SequentialNumberGuessWorkflowou StateMachineNumberGuessWorkflow, en fonction du workflow que vous avez effectué à l’étape précédente How to: Create a Workflow . Si vous ne substituez pas Workflow1 , vous obtiendrez des erreurs de build lors de la génération ou de l'exécution du workflow.

static void Main(string[] args)
{
    AutoResetEvent syncEvent = new AutoResetEvent(false);
    AutoResetEvent idleEvent = new AutoResetEvent(false);

    var inputs = new Dictionary<string, object>() { { "MaxNumber", 100 } };

    WorkflowApplication wfApp =
        new WorkflowApplication(new Workflow1(), inputs);

    wfApp.Completed = delegate (WorkflowApplicationCompletedEventArgs e)
    {
        int Turns = Convert.ToInt32(e.Outputs["Turns"]);
        Console.WriteLine("Congratulations, you guessed the number in {0} turns.", Turns);

        syncEvent.Set();
    };

    wfApp.Aborted = delegate (WorkflowApplicationAbortedEventArgs e)
    {
        Console.WriteLine(e.Reason);
        syncEvent.Set();
    };

    wfApp.OnUnhandledException = delegate (WorkflowApplicationUnhandledExceptionEventArgs e)
    {
        Console.WriteLine(e.UnhandledException.ToString());
        return UnhandledExceptionAction.Terminate;
    };

    wfApp.Idle = delegate (WorkflowApplicationIdleEventArgs e)
    {
        idleEvent.Set();
    };

    wfApp.Run();

    // Loop until the workflow completes.
    WaitHandle[] handles = new WaitHandle[] { syncEvent, idleEvent };
    while (WaitHandle.WaitAny(handles) != 0)
    {
        // Gather the user input and resume the bookmark.
        bool validEntry = false;
        while (!validEntry)
        {
            int Guess;
            if (!Int32.TryParse(Console.ReadLine(), out Guess))
            {
                Console.WriteLine("Please enter an integer.");
            }
            else
            {
                validEntry = true;
                wfApp.ResumeBookmark("EnterGuess", Guess);
            }
        }
    }
}
Sub Main()
    Dim syncEvent As New AutoResetEvent(False)
    Dim idleEvent As New AutoResetEvent(False)

    Dim inputs As New Dictionary(Of String, Object)
    inputs.Add("MaxNumber", 100)

    Dim wfApp As New WorkflowApplication(New Workflow1(), inputs)

    wfApp.Completed = _
        Sub(e As WorkflowApplicationCompletedEventArgs)
            Dim Turns As Integer = Convert.ToInt32(e.Outputs("Turns"))
            Console.WriteLine("Congratulations, you guessed the number in {0} turns.", Turns)

            syncEvent.Set()
        End Sub

    wfApp.Aborted = _
        Sub(e As WorkflowApplicationAbortedEventArgs)
            Console.WriteLine(e.Reason)
            syncEvent.Set()
        End Sub

    wfApp.OnUnhandledException = _
        Function(e As WorkflowApplicationUnhandledExceptionEventArgs)
            Console.WriteLine(e.UnhandledException)
            Return UnhandledExceptionAction.Terminate
        End Function

    wfApp.Idle = _
        Sub(e As WorkflowApplicationIdleEventArgs)
            idleEvent.Set()
        End Sub

    wfApp.Run()

    ' Loop until the workflow completes.
    Dim waitHandles As WaitHandle() = New WaitHandle() {syncEvent, idleEvent}
    Do While WaitHandle.WaitAny(waitHandles) <> 0
        'Gather the user input and resume the bookmark.
        Dim validEntry As Boolean = False
        Do While validEntry = False
            Dim Guess As Integer
            If Int32.TryParse(Console.ReadLine(), Guess) = False Then
                Console.WriteLine("Please enter an integer.")
            Else
                validEntry = True
                wfApp.ResumeBookmark("EnterGuess", Guess)
            End If
        Loop
    Loop
End Sub

Voir aussi