Delen via


Procedure: Een werkstroom uitvoeren

Dit onderwerp is een vervolg van de zelfstudie Aan de slag met Windows Workflow Foundation en beschrijft hoe u een werkstroomhost maakt en de werkstroom uitvoert die is gedefinieerd in de vorige procedure: Een werkstroomonderwerp maken.

Notitie

Elk onderwerp in de zelfstudie Aan de slag is afhankelijk van de vorige onderwerpen. Als u dit onderwerp wilt voltooien, moet u eerst het volgende voltooien : Een activiteit maken en een werkstroom maken.

Het werkstroomhostproject maken

  1. Open de oplossing uit de vorige procedure: Een activiteitsonderwerp maken met behulp van Visual Studio 2012.

  2. Klik met de rechtermuisknop op de WF45GettingStartedTutorial-oplossing in Solution Explorer en selecteer Toevoegen, Nieuw project.

    Tip

    Als het Venster Solution Explorer niet wordt weergegeven, selecteert u Solution Explorer in het menu Beeld .

  3. Selecteer in het geïnstalleerde knooppunt Visual C#, Workflow (of Visual Basic, Workflow).

    Notitie

    Afhankelijk van de programmeertaal die is geconfigureerd als de primaire taal in Visual Studio, bevindt het knooppunt Visual C# of Visual Basic zich mogelijk onder het knooppunt Overige talen in het geïnstalleerde knooppunt.

    Zorg ervoor dat .NET Framework 4.5 is geselecteerd in de vervolgkeuzelijst .NET Framework-versie. Selecteer De werkstroomconsoletoepassing in de lijst Werkstroom . Typ NumberGuessWorkflowHost in het vak Naam en klik op OK. Hiermee maakt u een starterwerkstroomtoepassing met basisondersteuning voor werkstroomhosting. Deze basishostingcode wordt gewijzigd en gebruikt om de werkstroomtoepassing uit te voeren.

  4. Klik met de rechtermuisknop op het zojuist toegevoegde NumberGuessWorkflowHost-project in Solution Explorer en selecteer Verwijzing toevoegen. Selecteer Oplossing in de lijst Verwijzing toevoegen, schakel het selectievakje naast NumberGuessWorkflowActivities in en klik op OK.

  5. Klik met de rechtermuisknop op Workflow1.xaml in Solution Explorer en kies Verwijderen. Klik op OK om te bevestigen.

De hostingcode van de werkstroom wijzigen

  1. Dubbelklik op Program.cs of Module1.vb in Solution Explorer om de code weer te geven.

    Tip

    Als het Venster Solution Explorer niet wordt weergegeven, selecteert u Solution Explorer in het menu Beeld .

    Omdat dit project is gemaakt met behulp van de werkstroomconsoletoepassingssjabloon , bevat Program.cs of Module1.vb de volgende basiscode voor het hosten van werkstromen.

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

    Deze gegenereerde hostingcode maakt gebruik van WorkflowInvoker. WorkflowInvoker biedt een eenvoudige manier om een werkstroom aan te roepen alsof het een methode-aanroep is en alleen kan worden gebruikt voor werkstromen die geen persistentie gebruiken. WorkflowApplication biedt een uitgebreider model voor het uitvoeren van werkstromen met meldingen van levenscyclusgebeurtenissen, uitvoeringsbeheer, hervatting van bladwijzers en persistentie. In dit voorbeeld worden bladwijzers gebruikt en WorkflowApplication gebruikt voor het hosten van de werkstroom. Voeg bovenaan Program.cs of Module1.vb onder de bestaande instructies voor importeren of importeren de volgende using instructie of importinstructie toe.

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

    Vervang de coderegels die worden gebruikt WorkflowInvoker door de volgende basishostingcode WorkflowApplication . Deze voorbeeldhostingcode demonstreert de basisstappen voor het hosten en aanroepen van een werkstroom, maar bevat nog niet de functionaliteit om de werkstroom uit dit onderwerp uit te voeren. In de volgende stappen wordt deze basiscode gewijzigd en worden aanvullende functies toegevoegd totdat de toepassing is voltooid.

    Notitie

    U moet in deze voorbeelden vervangen door Workflow1 FlowchartNumberGuessWorkflow, SequentialNumberGuessWorkflowof StateMachineNumberGuessWorkflow, afhankelijk van de werkstroom die u in de vorige procedure hebt voltooid: Een werkstroomstap maken. Als u deze niet vervangt Workflow1 , krijgt u buildfouten wanneer u de werkstroom probeert te bouwen of uit te voeren.

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

    Met deze code maakt u een WorkflowApplication, abonneert u zich op drie levenscyclusgebeurtenissen van de werkstroom, start u de werkstroom met een aanroep naar Runen wacht u totdat de werkstroom is voltooid. Wanneer de werkstroom is voltooid, wordt de AutoResetEvent set ingesteld en wordt de hosttoepassing voltooid.

Invoerargumenten van een werkstroom instellen

  1. Voeg de volgende instructie toe boven aan Program.cs of Module1.vb onder de bestaande using of Imports instructies.

  2. Vervang de coderegel waarmee de nieuwe WorkflowApplication wordt gemaakt door de volgende code waarmee een woordenlijst met parameters wordt gemaakt en doorgegeven aan de werkstroom wanneer deze wordt gemaakt.

    Notitie

    Workflow1 Vervang in deze voorbeelden door FlowchartNumberGuessWorkflow, SequentialNumberGuessWorkflowof StateMachineNumberGuessWorkflow, afhankelijk van de werkstroom die u in de vorige procedure hebt voltooid: Een werkstroomstap maken. Als u deze niet vervangt Workflow1 , krijgt u buildfouten wanneer u de werkstroom probeert te bouwen of uit te voeren.

    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)
    

    Deze woordenlijst bevat één element met een sleutel van MaxNumber. Sleutels in de invoerwoordenlijst komen overeen met invoerargumenten voor de hoofdactiviteit van de werkstroom. MaxNumber wordt door de werkstroom gebruikt om de bovengrens voor het willekeurig gegenereerde getal te bepalen.

Uitvoerargumenten van een werkstroom ophalen

  1. Wijzig de Completed handler om het aantal beurten op te halen en weer te geven dat door de werkstroom wordt gebruikt.

    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
    

Een bladwijzer hervatten

  1. Voeg de volgende code toe boven aan de Main methode net na de bestaande AutoResetEvent declaratie.

    AutoResetEvent idleEvent = new AutoResetEvent(false);
    
    Dim idleEvent As New AutoResetEvent(False)
    
  2. Voeg de volgende Idle handler toe net onder de bestaande drie werkstroomhandlers in Mainde levenscyclus.

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

    Telkens wanneer de werkstroom inactief wordt, wordt deze handler aangeroepen en wordt deze idleAction AutoResetEvent ingesteld. De code in de volgende stap gebruikt idleEvent en syncEvent om te bepalen of de werkstroom wacht op de volgende schatting of is voltooid.

    Notitie

    In dit voorbeeld gebruikt de hosttoepassing gebeurtenissen voor automatisch opnieuw instellen in de Completed en Idle handlers om de hosttoepassing te synchroniseren met de voortgang van de werkstroom. Het is niet nodig om te blokkeren en te wachten totdat de werkstroom inactief is voordat een bladwijzer wordt hervat, maar in dit voorbeeld zijn de synchronisatie-gebeurtenissen vereist, zodat de host weet of de werkstroom is voltooid of dat er wordt gewacht op meer gebruikersinvoer met behulp van de Bookmark. Zie Bladwijzers voor meer informatie.

  3. Verwijder de aanroep naar WaitOneen vervang deze door code om invoer van de gebruiker te verzamelen en de Bookmarkaanroep te hervatten.

    Verwijder de volgende regel code.

    syncEvent.WaitOne();
    
    syncEvent.WaitOne()
    

    Vervang deze door het volgende voorbeeld.

    // 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
    

De toepassing bouwen en uitvoeren

  1. Klik met de rechtermuisknop op NumberGuessWorkflowHost in Solution Explorer en selecteer Instellen als Opstartproject.

  2. Druk op Ctrl+F5 om de toepassing te bouwen en uit te voeren. Probeer het getal in zo weinig mogelijk bochten te raden.

    Als u de toepassing wilt uitproberen met een van de andere werkstroomstijlen, vervangt Workflow1 u de code die de WorkflowApplication toepassing maakt met FlowchartNumberGuessWorkflow, SequentialNumberGuessWorkflowof StateMachineNumberGuessWorkflow, afhankelijk van de gewenste werkstroomstijl.

    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)
    

    Zie het volgende onderwerp: Een langlopende werkstroom maken en uitvoeren voor instructies over het toevoegen van persistentie aan een werkstroomtoepassing.

Opmerking

Het volgende voorbeeld is de volledige codevermelding voor de Main methode.

Notitie

Workflow1 Vervang in deze voorbeelden door FlowchartNumberGuessWorkflow, SequentialNumberGuessWorkflowof StateMachineNumberGuessWorkflow, afhankelijk van de werkstroom die u in de vorige procedure hebt voltooid: Een werkstroomstap maken. Als u deze niet vervangt Workflow1 , krijgt u buildfouten wanneer u de werkstroom probeert te bouwen of uit te voeren.

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

Zie ook