Freigeben über


Vorgehensweise: Ausführen eines Workflows

Dieses Thema ist eine Fortsetzung des Tutorials „Windows Workflow Foundation: Erste Schritte“. Hierin wird beschrieben, wie Sie einen Workflowhost erstellen und den im vorherigen Thema How to: Create a Workflow definierten Workflow ausführen.

Hinweis

Ein Thema im Lernprogramm "Erste Schritte" hängt jeweils von den vorherigen Themen ab. Um dieses Thema verwenden zu können, müssen Sie zuerst How to: Create an Activity und How to: Create a Workflowdurcharbeiten und abschließen.

So erstellen Sie das Workflowhostprojekt

  1. Öffnen Sie die Projektmappe des vorherigen Themas Vorgehensweise: Erstellen einer Aktivität mit Visual Studio 2012 durcharbeiten und abschließen.

  2. Klicken Sie im Projektmappen-Explorer mit der rechten Maustaste auf WF45GettingStartedTutorial , zeigen Sie auf Hinzufügen, und wählen Sie Neues Projektaus.

    Tipp

    Wird das Fenster Projektmappen-Explorer nicht angezeigt, wählen Sie Projektmappen-Explorer im Menü Ansicht aus.

  3. Wählen Sie im Knoten Installiert die Option Visual C#und anschließend Workflow (oder Visual Basic, Workflow) aus.

    Hinweis

    Abhängig davon, welche Programmiersprache als primäre Sprache in Visual Studio konfiguriert ist, kann sich der Knoten Visual C# oder Visual Basic unter dem Knoten Andere Sprachen im Knoten Installiert befinden.

    Stellen Sie sicher, dass .NET Framework 4.5 in der Dropdownliste für die .NET Framework-Version ausgewählt ist. Wählen Sie in der Liste Workflow die Option Konsolenanwendung für Workflows aus. Geben Sie im Feld NumberGuessWorkflowHost Name die Bezeichnung ein, und klicken Sie auf OK. Auf diese Weise wird eine Start-Workflowanwendung mit grundlegender Unterstützung von Workflowhosting erstellt. Dieser grundlegende Hostingcode wird geändert und zum Ausführen der Workflowanwendung verwendet.

  4. Klicken Sie im Projektmappen-Explorer mit der rechten Maustaste auf das neu hinzugefügte Projekt NumberGuessWorkflowHost , und wählen Sie Verweis hinzufügenaus. Wählen Sie in der Liste Verweis hinzufügen den Eintrag Projektmappe aus, aktivieren Sie das Kontrollkästchen neben NumberGuessWorkflowActivities, und klicken Sie auf OK.

  5. Klicken Sie im Projektmappen-Explorer mit der rechten Maustaste auf Workflow1.xaml , und wählen Sie Löschenaus. Klicken Sie auf OK , um zu bestätigen.

So ändern Sie den Code zum Hosten von Workflows

  1. Doppelklicken Sie im Projektmappen-Explorer auf Program.cs oder Module1.vb , um den Code anzuzeigen.

    Tipp

    Wird das Fenster Projektmappen-Explorer nicht angezeigt, wählen Sie Projektmappen-Explorer im Menü Ansicht aus.

    Da dieses Projekt mit der Vorlage Konsolenanwendung für Workflows erstellt wurde, enthält Program.cs oder Module1.vb den folgenden grundlegenden Code zum Hosten von Workflows.

    ' 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);
    

    Der generierte Hostingcode verwendet WorkflowInvoker. WorkflowInvoker stellt eine einfache Möglichkeit zum Aufrufen eines Workflows bereit, so als handelte es sich um einen Methodenaufruf, und kann nur für Workflows verwendet werden, die keine Persistenz verwenden. WorkflowApplication bietet ein umfangreicheres Modell zum Ausführen von Workflows, die Benachrichtigungen über Lebenszyklusereignisse, Ausführungssteuerung, Wiederaufnahme von Lesezeichen und Persistenz enthalten. In diesem Beispiel werden Lesezeichen verwendet, und WorkflowApplication wird zum Hosten des Workflows genutzt. Fügen Sie die folgende using - oder Imports -Anweisung am Anfang von Program.cs oder Module1.vb unter der vorhandenen using - oder Imports -Anweisung hinzu.

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

    Ersetzen Sie die Codezeilen, in denen WorkflowInvoker mit dem folgenden grundlegenden WorkflowApplication -Hostingcode verwendet wird. In diesem Beispielhostingcode werden die grundlegenden Schritte zum Hosten und das Aufrufen eines Workflows veranschaulicht, das Beispiel enthält jedoch noch nicht die Funktionalität zum erfolgreichen Ausführen des Workflows aus diesem Thema. In den folgenden Schritten wird der grundlegende Code geändert, und es werden zusätzliche Funktionen hinzugefügt, bis die Anwendung abgeschlossen wurde.

    Hinweis

    Sie müssen Workflow1 in diesen Beispielen durch FlowchartNumberGuessWorkflow, SequentialNumberGuessWorkflow oder StateMachineNumberGuessWorkflow ersetzen, je nachdem, welchen Workflow Sie im vorherigen Schritt How to: Create a Workflow abgeschlossen haben. Wenn Sie Workflow1 nicht ersetzen, erhalten Sie Buildfehler, wenn Sie versuchen, den Workflow zu erstellen oder auszuführen.

    AutoResetEvent syncEvent = new AutoResetEvent(false);
    
    WorkflowApplication wfApp =
        new WorkflowApplication(_wf);
    
    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()
    

    In diesem Code wird ein WorkflowApplication-Element erstellt, es werden drei Lebenszyklusereignisse des Workflows abonniert, der Workflow wird per Aufruf von Rungestartet, und dann wird auf den Abschluss des Workflows gewartet. Nach Abschluss des Workflows wird AutoResetEvent festgelegt, und die Hostanwendung wird abgeschlossen.

So legen Sie die Eingabeargumente eines Workflows fest

  1. Fügen Sie oben in der Datei Program.cs oder Module1.vb unter den vorhandenen using - oder Imports -Anweisung die folgende Anweisung hinzu.

  2. Ersetzen Sie die Codezeile, die das neue WorkflowApplication -Element erstellt, durch den folgenden Code, der ein Wörterbuch mit Parametern erstellt und dieses nach seiner Erstellung an den Workflow übergibt.

    Hinweis

    Ersetzen Sie Workflow1 in diesen Beispielen durch FlowchartNumberGuessWorkflow, und wählen Sie SequentialNumberGuessWorkflow, und wählen Sie or StateMachineNumberGuessWorkflow, und wählen Sie depending on which workflow you completed in the previous How to: Create a Workflow abgeschlossen haben. Wenn Sie Workflow1 nicht ersetzen, erhalten Sie Buildfehler, wenn Sie versuchen, den Workflow zu erstellen oder auszuführen.

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

    Dieses Wörterbuch enthält ein Element mit dem Schlüssel MaxNumber. Schlüssel im Eingabewörterbuch entsprechen Eingabeargumenten in der Stammaktivität des Workflows. MaxNumber wird vom Workflow verwendet, um die Obergrenze für die zufällig generierte Zahl zu bestimmen.

So rufen Sie die Ausgabeargumente eines Workflows ab

  1. Ändern Sie den Completed -Handler, um die Anzahl der vom Workflow verwendeten Durchgänge (turns) abzurufen und anzuzeigen.

    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
    

So nehmen Sie ein Lesezeichen wieder auf

  1. Fügen Sie oben in der Main -Methode direkt nach der bestehenden AutoResetEvent -Deklaration den folgenden Code hinzu.

    AutoResetEvent idleEvent = new AutoResetEvent(false);
    
    Dim idleEvent As New AutoResetEvent(False)
    
  2. Fügen Sie direkt unterhalb der drei bestehenden Lebenszyklushandler des Workflows im Abschnitt Idle den folgenden Main-Handler hinzu.

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

    Immer, wenn der Workflow dann in den Leerlaufzustand eintritt und auf den nächsten Lösungsversuch wartet, wird dieser Handler aufgerufen und idleAction AutoResetEvent festgelegt. Der Code im folgenden Schritt verwendet idleEvent und syncEvent , um zu ermitteln, ob der Workflow auf den nächsten Lösungsversuch wartet oder abgeschlossen ist.

    Hinweis

    In diesem Beispiel verwendet die Hostanwendung AutoReset-Ereignisse in den Handlern Completed und Idle , um die Hostanwendung mit dem Status des Workflows zu synchronisieren. Das Blockieren und das Warten auf den Eintritt des Workflows in den Leerlaufzustand ist nicht erforderlich, bevor ein Lesezeichen wiederaufgenommen wird. In diesem Beispiel sind die Synchronisierungsereignisse jedoch erforderlich, damit der Host weiß, ob der Workflow abgeschlossen ist oder ob dieser mithilfe von Bookmarkauf weitere Benutzereingaben wartet. Weitere Informationen finden Sie unter Textmarken.

  3. Entfernen Sie den Aufruf von WaitOne, und ersetzen Sie diesen durch Code zum Erfassen der Eingabe des Benutzers und zum Wiederaufnehmen von Bookmark.

    Entfernen Sie die folgende Codezeile.

    syncEvent.WaitOne();
    
    syncEvent.WaitOne()
    

    Ersetzen Sie diese durch den folgenden Beispielcode.

    // 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)
        {
            if (!Int32.TryParse(Console.ReadLine(), out int 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
    

So erstellen Sie die Anwendung und führen sie aus

  1. Klicken Sie im Projektmappen-Explorer mit der rechten Maustaste auf NumberGuessWorkflowHost , und wählen Sie Als Startprojekt festlegenaus.

  2. Drücken Sie STRG+F5, um die Anwendung zu erstellen und auszuführen. Versuchen Sie, die Zahl in möglichst wenigen Durchgängen zu erraten.

    Um die Anwendung mit einem der anderen Workflowtypen auszuprobieren, ersetzen Sie Workflow1 im Code, durch den WorkflowApplication erstellt wird, durch FlowchartNumberGuessWorkflow, SequentialNumberGuessWorkflowoder StateMachineNumberGuessWorkflow, je nachdem, welcher Workflowtyp gewünscht ist.

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

    Eine Anleitung dazu, wie Sie einer Workflowanwendung Persistenz hinzufügen, finden Sie im nächsten Thema: How to: Create and Run a Long Running Workflow.

Beispiel

Das folgende Beispiel ist die vollständige Codeauflistung für die Main -Methode.

Hinweis

Ersetzen Sie Workflow1 in diesen Beispielen durch FlowchartNumberGuessWorkflow, und wählen Sie SequentialNumberGuessWorkflow, und wählen Sie or StateMachineNumberGuessWorkflow, und wählen Sie depending on which workflow you completed in the previous How to: Create a Workflow abgeschlossen haben. Wenn Sie Workflow1 nicht ersetzen, erhalten Sie Buildfehler, wenn Sie versuchen, den Workflow zu erstellen oder auszuführen.

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(_wf, inputs)
    {

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

            syncEvent.Set();
        },

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

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

        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)
        {
            if (!Int32.TryParse(Console.ReadLine(), out int 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

Weitere Informationen