Delen via


Een langlopende werkstroom maken en uitvoeren

Een van de centrale functies van Windows Workflow Foundation (WF) is de mogelijkheid van de runtime om niet-actieve werkstromen in een database te behouden en te verwijderen. De stappen in Procedure: Een werkstroom uitvoeren heeft de basisbeginselen van het hosten van werkstromen gedemonstreerd met behulp van een consoletoepassing. Voorbeelden zijn weergegeven van beginwerkstromen, werkstroomlevenscyclushandlers en het hervatten van bladwijzers. Om de werkstroompersistentie effectief te demonstreren, is een complexere werkstroomhost vereist die ondersteuning biedt voor het starten en hervatten van meerdere werkstroomexemplaren. Deze stap in de zelfstudie laat zien hoe u een Windows-formulierhosttoepassing maakt die ondersteuning biedt voor het starten en hervatten van meerdere werkstroomexemplaren, werkstroompersistentie en biedt een basis voor de geavanceerde functies, zoals bijhouden en versiebeheer die worden gedemonstreerd in de volgende zelfstudiestappen.

Notitie

In deze zelfstudiestap en de volgende stappen worden alle drie de werkstroomtypen gebruikt: Een werkstroom maken.

De persistentiedatabase maken

  1. Open SQL Server Management Studio en maak verbinding met de lokale server, bijvoorbeeld .\SQLEXPRESS. Klik met de rechtermuisknop op het knooppunt Databases op de lokale server en selecteer Nieuwe database. Geef de nieuwe database de naam WF45GettingStartedTutorial, accepteer alle andere waarden en selecteer OK.

    Notitie

    Zorg ervoor dat u de machtiging Database maken hebt op de lokale server voordat u de database maakt.

  2. Kies Openen, Bestand in het menu Bestand . Blader naar de volgende map: C:\Windows\Microsoft.NET\Framework\v4.0.30319\sql\en

    Selecteer de volgende twee bestanden en klik op Openen.

    • SqlWorkflowInstanceStoreLogic.sql

    • SqlWorkflowInstanceStoreSchema.sql

  3. Kies SqlWorkflowInstanceStoreSchema.sql in het menu Venster . Zorg ervoor dat WF45GettingStartedTutorial is geselecteerd in de vervolgkeuzelijst Beschikbare databases en kies Uitvoeren in het menu Query.

  4. Kies SqlWorkflowInstanceStoreLogic.sql in het menu Venster . Zorg ervoor dat WF45GettingStartedTutorial is geselecteerd in de vervolgkeuzelijst Beschikbare databases en kies Uitvoeren in het menu Query.

    Waarschuwing

    Het is belangrijk om de vorige twee stappen in de juiste volgorde uit te voeren. Als de query's niet op volgorde worden uitgevoerd, treden er fouten op en is de persistentiedatabase niet juist geconfigureerd.

De verwijzing naar de DurableInstancing-assembly's toevoegen

  1. Klik met de rechtermuisknop op NumberGuessWorkflowHost in Solution Explorer en selecteer Verwijzing toevoegen.

  2. Selecteer Assembly's in de lijst Verwijzing toevoegen en typ DurableInstancing in het vak Zoekassembly's . Hierdoor worden de assembly's gefilterd en kunnen de gewenste verwijzingen gemakkelijker worden geselecteerd.

  3. Schakel het selectievakje naast System.Activities.DurableInstancing en System.Runtime.DurableInstancing in de lijst met zoekresultaten in en klik op OK.

Het hostformulier voor de werkstroom maken

  1. Klik met de rechtermuisknop op NumberGuessWorkflowHost in Solution Explorer en kies Toevoegen, Nieuw item.

  2. Kies Windows-formulier in de lijst geïnstalleerde sjablonen, typ WorkflowHostForm het vak Naam en klik op Toevoegen.

  3. Configureer de volgende eigenschappen op het formulier.

    Eigenschappen Weergegeven als
    FormBorderStyle FixedSingle
    MaximaliseerBox Onwaar
    Tekengrootte 400, 420
  4. Voeg de volgende besturingselementen toe aan het formulier in de opgegeven volgorde en configureer de eigenschappen zoals omgeleid.

    Control Eigenschap: waarde
    Knop Naam: NewGame

    Locatie: 13, 13

    Grootte: 75, 23

    Tekst: Nieuw spel
    Label Locatie: 94, 18

    Tekst: Een getal raden van 1 tot
    Keuzelijst met invoervak Naam: NumberRange

    DropDownStyle: DropDownList

    Items: 10, 100, 1000

    Locatie: 228, 12

    Grootte: 143, 21
    Label Locatie: 13, 43

    Tekst: werkstroomtype
    Keuzelijst met invoervak Naam: WorkflowType

    DropDownStyle: DropDownList

    Items: StateMachineNumberGuessWorkflow, FlowchartNumberGuessWorkflow, SequentialNumberGuessWorkflow

    Locatie: 94, 40

    Grootte: 277, 21
    Label Naam: WorkflowVersion

    Locatie: 13, 362

    Tekst: werkstroomversie
    Groepsvak Locatie: 13, 67

    Grootte: 358, 287

    Tekst: Game

    Notitie

    Wanneer u de volgende besturingselementen toevoegt, plaatst u deze in het groepsvak.

    Control Eigenschap: waarde
    Label Locatie: 7, 20

    Tekst: Id van werkstroomexemplaren
    Keuzelijst met invoervak Naam: InstanceId

    DropDownStyle: DropDownList

    Locatie: 121, 17

    Grootte: 227, 21
    Label Locatie: 7, 47

    Tekst: Schatting
    TextBox Naam: Schatting

    Locatie: 50, 44

    Grootte: 65, 20
    Knop Naam: EnterGuess

    Locatie: 121, 42

    Grootte: 75, 23

    Tekst: Schatting invoeren
    Knop Naam: QuitGame

    Locatie: 274, 42

    Grootte: 75, 23

    Tekst: Afsluiten
    TextBox Naam: WorkflowStatus

    Locatie: 10, 73

    Multiline: Waar

    Alleen-lezen: Waar

    Schuifbalken: verticaal

    Grootte: 338, 208
  5. Stel de eigenschap AcceptButton van het formulier in op EnterGuess.

In het volgende voorbeeld ziet u het ingevulde formulier.

Schermopname van een Werkstroomhostformulier voor Windows Workflow Foundation.

De eigenschappen en helpermethoden van het formulier toevoegen

Met de stappen in deze sectie worden eigenschappen en helpermethoden toegevoegd aan de formulierklasse waarmee de gebruikersinterface van het formulier wordt geconfigureerd ter ondersteuning van actieve en hervatting van werkstromen voor het raden van getallen.

  1. Klik met de rechtermuisknop op WorkflowHostForm in Solution Explorer en kies Code weergeven.

  2. Voeg de volgende using (of Imports) instructies toe boven aan het bestand met de andere using (of Imports) instructies.

    Imports System.Activities
    Imports System.Activities.DurableInstancing
    Imports System.Data.SqlClient
    Imports System.IO
    Imports System.Windows.Forms
    
    using System.Activities;
    using System.Activities.DurableInstancing;
    using System.Data.SqlClient;
    using System.IO;
    using System.Windows.Forms;
    
  3. Voeg de volgende liddeclaraties toe aan de klasse WorkflowHostForm .

    Belangrijk

    Microsoft raadt u aan de veiligste verificatiestroom te gebruiken die beschikbaar is. Als u verbinding maakt met Azure SQL, is Managed Identities voor Azure-resources de aanbevolen verificatiemethode.

    Const connectionString = "Server=.\SQLEXPRESS;Initial Catalog=WF45GettingStartedTutorial;Integrated Security=SSPI"
    Dim store As SqlWorkflowInstanceStore
    Dim workflowStarting As Boolean
    
    const string connectionString = "Server=.\\SQLEXPRESS;Initial Catalog=WF45GettingStartedTutorial;Integrated Security=SSPI";
    SqlWorkflowInstanceStore store;
    bool workflowStarting;
    

    Notitie

    Als uw verbindingsreeks anders is, werkt connectionString u deze bij om naar uw database te verwijzen.

  4. Voeg een WorkflowInstanceId eigenschap toe aan de WorkflowFormHost klasse.

    Public ReadOnly Property WorkflowInstanceId() As Guid
        Get
            If InstanceId.SelectedIndex = -1 Then
                Return Guid.Empty
            Else
                Return New Guid(InstanceId.SelectedItem.ToString())
            End If
        End Get
    End Property
    
    public Guid WorkflowInstanceId
    {
        get
        {
            return InstanceId.SelectedIndex == -1 ? Guid.Empty : (Guid)InstanceId.SelectedItem;
        }
    }
    

    De InstanceId keuzelijst met invoervak bevat een lijst met persistente werkstroomexemplaren en de WorkflowInstanceId eigenschap retourneert de momenteel geselecteerde werkstroom.

  5. Voeg een handler toe voor de formulier Load gebeurtenis. Als u de handler wilt toevoegen, schakelt u over naar de ontwerpweergave voor het formulier, klikt u op het pictogram Gebeurtenissen boven aan het venster Eigenschappen en dubbelklikt u op Laden.

    Private Sub WorkflowHostForm_Load(sender As Object, e As EventArgs) Handles Me.Load
    
    End Sub
    
    private void WorkflowHostForm_Load(object sender, EventArgs e)
    {
    
    }
    
  6. Voeg de volgende code toe aan WorkflowHostForm_Load.

    ' Initialize the store and configure it so that it can be used for
    ' multiple WorkflowApplication instances.
    store = New SqlWorkflowInstanceStore(connectionString)
    WorkflowApplication.CreateDefaultInstanceOwner(store, Nothing, WorkflowIdentityFilter.Any)
    
    ' Set default ComboBox selections.
    NumberRange.SelectedIndex = 0
    WorkflowType.SelectedIndex = 0
    
    ListPersistedWorkflows()
    
    // Initialize the store and configure it so that it can be used for
    // multiple WorkflowApplication instances.
    store = new SqlWorkflowInstanceStore(connectionString);
    WorkflowApplication.CreateDefaultInstanceOwner(store, null, WorkflowIdentityFilter.Any);
    
    // Set default ComboBox selections.
    NumberRange.SelectedIndex = 0;
    WorkflowType.SelectedIndex = 0;
    
    ListPersistedWorkflows();
    

    Wanneer het formulier wordt geladen, worden de SqlWorkflowInstanceStore keuzelijsten met invoervakbereik en werkstroomtype ingesteld op standaardwaarden en worden de persistente werkstroomexemplaren toegevoegd aan de InstanceId keuzelijst met invoervak.

  7. Voeg een SelectedIndexChanged handler toe voor InstanceId. Als u de handler wilt toevoegen, schakelt u over naar de ontwerpweergave voor het formulier, selecteert u de InstanceId keuzelijst met invoervak, klikt u op het pictogram Gebeurtenissen boven aan het venster Eigenschappen en dubbelklikt u op SelectedIndexChanged.

    Private Sub InstanceId_SelectedIndexChanged(sender As Object, e As EventArgs) Handles InstanceId.SelectedIndexChanged
    
    End Sub
    
    private void InstanceId_SelectedIndexChanged(object sender, EventArgs e)
    {
    
    }
    
  8. Voeg de volgende code toe aan InstanceId_SelectedIndexChanged. Wanneer de gebruiker een werkstroom selecteert met behulp van de keuzelijst met invoervak, wordt het statusvenster bijgewerkt.

    If InstanceId.SelectedIndex = -1 Then
        Return
    End If
    
    ' Clear the status window.
    WorkflowStatus.Clear()
    
    ' Get the workflow version and display it.
    ' If the workflow is just starting then this info will not
    ' be available in the persistence store so do not try and retrieve it.
    If Not workflowStarting Then
        Dim instance As WorkflowApplicationInstance = _
            WorkflowApplication.GetInstance(WorkflowInstanceId, store)
    
        WorkflowVersion.Text = _
            WorkflowVersionMap.GetIdentityDescription(instance.DefinitionIdentity)
    
        ' Unload the instance.
        instance.Abandon()
    End If
    
    if (InstanceId.SelectedIndex == -1)
    {
        return;
    }
    
    // Clear the status window.
    WorkflowStatus.Clear();
    
    // Get the workflow version and display it.
    // If the workflow is just starting then this info will not
    // be available in the persistence store so do not try and retrieve it.
    if (!workflowStarting)
    {
        WorkflowApplicationInstance instance =
            WorkflowApplication.GetInstance(this.WorkflowInstanceId, store);
    
        WorkflowVersion.Text =
            WorkflowVersionMap.GetIdentityDescription(instance.DefinitionIdentity);
    
        // Unload the instance.
        instance.Abandon();
    }
    
  9. Voeg de volgende ListPersistedWorkflows methode toe aan de formulierklasse.

    Private Sub ListPersistedWorkflows()
        Using localCon As New SqlConnection(connectionString)
            Dim localCmd As String = _
                "SELECT [InstanceId] FROM [System.Activities.DurableInstancing].[Instances] ORDER BY [CreationTime]"
    
            Dim cmd As SqlCommand = localCon.CreateCommand()
            cmd.CommandText = localCmd
            localCon.Open()
            Using reader As SqlDataReader = cmd.ExecuteReader(CommandBehavior.CloseConnection)
    
                While (reader.Read())
                    ' Get the InstanceId of the persisted Workflow.
                    Dim id As Guid = Guid.Parse(reader(0).ToString())
                    InstanceId.Items.Add(id)
                End While
            End Using
        End Using
    End Sub
    
    using (var localCon = new SqlConnection(connectionString))
    {
        string localCmd =
            "SELECT [InstanceId] FROM [System.Activities.DurableInstancing].[Instances] ORDER BY [CreationTime]";
    
        SqlCommand cmd = localCon.CreateCommand();
        cmd.CommandText = localCmd;
        localCon.Open();
        using (SqlDataReader reader = cmd.ExecuteReader(CommandBehavior.CloseConnection))
        {
            while (reader.Read())
            {
                // Get the InstanceId of the persisted Workflow.
                Guid id = Guid.Parse(reader[0].ToString());
                InstanceId.Items.Add(id);
            }
        }
    }
    

    ListPersistedWorkflows voert een query uit op het exemplaararchief voor persistente werkstroomexemplaren en voegt de exemplaar-id's toe aan de cboInstanceId keuzelijst met invoervak.

  10. Voeg de volgende UpdateStatus methode en de bijbehorende gemachtigde toe aan de formulierklasse. Met deze methode wordt het statusvenster op het formulier bijgewerkt met de status van de huidige actieve werkstroom.

    Private Delegate Sub UpdateStatusDelegate(msg As String)
    Public Sub UpdateStatus(msg As String)
        ' We may be on a different thread so we need to
        ' make this call using BeginInvoke.
        If InvokeRequired Then
            BeginInvoke(New UpdateStatusDelegate(AddressOf UpdateStatus), msg)
        Else
            If Not msg.EndsWith(vbCrLf) Then
                msg = msg & vbCrLf
            End If
    
            WorkflowStatus.AppendText(msg)
    
            ' Ensure that the newly added status is visible.
            WorkflowStatus.SelectionStart = WorkflowStatus.Text.Length
            WorkflowStatus.ScrollToCaret()
        End If
    End Sub
    
    private delegate void UpdateStatusDelegate(string msg);
    public void UpdateStatus(string msg)
    {
        // We may be on a different thread so we need to
        // make this call using BeginInvoke.
        if (InvokeRequired)
        {
            BeginInvoke(new UpdateStatusDelegate(UpdateStatus), msg);
        }
        else
        {
            if (!msg.EndsWith("\r\n"))
            {
                msg += "\r\n";
            }
            WorkflowStatus.AppendText(msg);
    
            WorkflowStatus.SelectionStart = WorkflowStatus.Text.Length;
            WorkflowStatus.ScrollToCaret();
        }
    }
    
  11. Voeg de volgende GameOver methode en de bijbehorende gemachtigde toe aan de formulierklasse. Wanneer een werkstroom is voltooid, wordt met deze methode de formuliergebruikersinterface bijgewerkt door de exemplaar-id van de voltooide werkstroom uit de keuzelijst met invoervak InstanceId te verwijderen.

    Private Delegate Sub GameOverDelegate()
    Private Sub GameOver()
        If InvokeRequired Then
            BeginInvoke(New GameOverDelegate(AddressOf GameOver))
        Else
            ' Remove this instance from the InstanceId combo box.
            InstanceId.Items.Remove(InstanceId.SelectedItem)
            InstanceId.SelectedIndex = -1
        End If
    End Sub
    
    private delegate void GameOverDelegate();
    private void GameOver()
    {
        if (InvokeRequired)
        {
            BeginInvoke(new GameOverDelegate(GameOver));
        }
        else
        {
            // Remove this instance from the combo box.
            InstanceId.Items.Remove(InstanceId.SelectedItem);
            InstanceId.SelectedIndex = -1;
        }
    }
    

Het exemplaararchief, de handlers voor de levenscyclus van werkstromen en extensies configureren

  1. Voeg een ConfigureWorkflowApplication methode toe aan de formulierklasse.

    Private Sub ConfigureWorkflowApplication(wfApp As WorkflowApplication)
    
    End Sub
    
    private void ConfigureWorkflowApplication(WorkflowApplication wfApp)
    {
    }
    

    Met deze methode configureert u de WorkflowApplicationgewenste extensies en voegt u handlers toe voor de levenscyclus van de werkstroom.

  2. Geef ConfigureWorkflowApplicationin , geef de SqlWorkflowInstanceStore voor de WorkflowApplication.

    ' Configure the persistence store.
    wfApp.InstanceStore = store
    
    // Configure the persistence store.
    wfApp.InstanceStore = store;
    
  3. Maak vervolgens een StringWriter exemplaar en voeg deze toe aan de Extensions verzameling van de WorkflowApplication. Wanneer een StringWriter wordt toegevoegd aan de extensies, worden alle WriteLine activiteitsuitvoer vastgelegd. Wanneer de werkstroom niet actief wordt, kan de WriteLine uitvoer worden geëxtraheerd uit het StringWriter formulier en worden weergegeven.

    ' Add a StringWriter to the extensions. This captures the output
    ' from the WriteLine activities so we can display it in the form.
    Dim sw As New StringWriter()
    wfApp.Extensions.Add(sw)
    
    // Add a StringWriter to the extensions. This captures the output
    // from the WriteLine activities so we can display it in the form.
    var sw = new StringWriter();
    wfApp.Extensions.Add(sw);
    
  4. Voeg de volgende handler toe voor de Completed gebeurtenis. Wanneer een werkstroom is voltooid, wordt het aantal beurten om te raden dat het getal wordt weergegeven in het statusvenster. Als de werkstroom wordt beëindigd, wordt de uitzonderingsinformatie die de beëindiging heeft veroorzaakt, weergegeven. Aan het einde van de handler wordt de GameOver methode aangeroepen, waardoor de voltooide werkstroom uit de lijst met werkstromen wordt verwijderd.

    wfApp.Completed = _
        Sub(e As WorkflowApplicationCompletedEventArgs)
            If e.CompletionState = ActivityInstanceState.Faulted Then
                UpdateStatus($"Workflow Terminated. Exception: {e.TerminationException.GetType().FullName}{vbCrLf}{e.TerminationException.Message}")
            ElseIf e.CompletionState = ActivityInstanceState.Canceled Then
                UpdateStatus("Workflow Canceled.")
            Else
                Dim turns As Integer = Convert.ToInt32(e.Outputs("Turns"))
                UpdateStatus($"Congratulations, you guessed the number in {turns} turns.")
            End If
            GameOver()
        End Sub
    
    wfApp.Completed = delegate(WorkflowApplicationCompletedEventArgs e)
    {
        if (e.CompletionState == ActivityInstanceState.Faulted)
        {
            UpdateStatus($"Workflow Terminated. Exception: {e.TerminationException.GetType().FullName}\r\n{e.TerminationException.Message}");
        }
        else if (e.CompletionState == ActivityInstanceState.Canceled)
        {
            UpdateStatus("Workflow Canceled.");
        }
        else
        {
            int turns = Convert.ToInt32(e.Outputs["Turns"]);
            UpdateStatus($"Congratulations, you guessed the number in {turns} turns.");
        }
        GameOver();
    };
    
  5. Voeg het volgende Aborted en OnUnhandledException de handlers toe. De GameOver methode wordt niet aangeroepen vanuit de Aborted handler omdat wanneer een werkstroomexemplaren worden afgebroken, deze niet wordt beëindigd en het is mogelijk om het exemplaar op een later tijdstip te hervatten.

    wfApp.Aborted = _
        Sub(e As WorkflowApplicationAbortedEventArgs)
            UpdateStatus($"Workflow Aborted. Exception: {e.Reason.GetType().FullName}{vbCrLf}{e.Reason.Message}")
        End Sub
    
    wfApp.OnUnhandledException = _
        Function(e As WorkflowApplicationUnhandledExceptionEventArgs)
            UpdateStatus($"Unhandled Exception: {e.UnhandledException.GetType().FullName}{vbCrLf}{e.UnhandledException.Message}")
            GameOver()
            Return UnhandledExceptionAction.Terminate
        End Function
    
    wfApp.Aborted = delegate(WorkflowApplicationAbortedEventArgs e)
    {
        UpdateStatus($"Workflow Aborted. Exception: {e.Reason.GetType().FullName}\r\n{e.Reason.Message}");
    };
    
    wfApp.OnUnhandledException = delegate(WorkflowApplicationUnhandledExceptionEventArgs e)
    {
        UpdateStatus($"Unhandled Exception: {e.UnhandledException.GetType().FullName}\r\n{e.UnhandledException.Message}");
        GameOver();
        return UnhandledExceptionAction.Terminate;
    };
    
  6. Voeg de volgende PersistableIdle handler toe. Deze handler haalt de StringWriter extensie op die is toegevoegd, extraheert de uitvoer van de WriteLine activiteiten en geeft deze weer in het statusvenster.

    wfApp.PersistableIdle = _
        Function(e As WorkflowApplicationIdleEventArgs)
            ' Send the current WriteLine outputs to the status window.
            Dim writers = e.GetInstanceExtensions(Of StringWriter)()
            For Each writer In writers
                UpdateStatus(writer.ToString())
            Next
            Return PersistableIdleAction.Unload
        End Function
    
    wfApp.PersistableIdle = delegate(WorkflowApplicationIdleEventArgs e)
    {
        // Send the current WriteLine outputs to the status window.
        var writers = e.GetInstanceExtensions<StringWriter>();
        foreach (var writer in writers)
        {
            UpdateStatus(writer.ToString());
        }
        return PersistableIdleAction.Unload;
    };
    

    De PersistableIdleAction opsomming heeft drie waarden: None, Persisten Unload. Persist zorgt ervoor dat de werkstroom blijft bestaan, maar dat zorgt er niet voor dat de werkstroom wordt uitgeladen. Unload zorgt ervoor dat de werkstroom behouden blijft en wordt uitgeladen.

    Het volgende voorbeeld is de voltooide ConfigureWorkflowApplication methode.

    Private Sub ConfigureWorkflowApplication(wfApp As WorkflowApplication)
        ' Configure the persistence store.
        wfApp.InstanceStore = store
    
        ' Add a StringWriter to the extensions. This captures the output
        ' from the WriteLine activities so we can display it in the form.
        Dim sw As New StringWriter()
        wfApp.Extensions.Add(sw)
    
        wfApp.Completed = _
            Sub(e As WorkflowApplicationCompletedEventArgs)
                If e.CompletionState = ActivityInstanceState.Faulted Then
                    UpdateStatus($"Workflow Terminated. Exception: {e.TerminationException.GetType().FullName}{vbCrLf}{e.TerminationException.Message}")
                ElseIf e.CompletionState = ActivityInstanceState.Canceled Then
                    UpdateStatus("Workflow Canceled.")
                Else
                    Dim turns As Integer = Convert.ToInt32(e.Outputs("Turns"))
                    UpdateStatus($"Congratulations, you guessed the number in {turns} turns.")
                End If
                GameOver()
            End Sub
    
        wfApp.Aborted = _
            Sub(e As WorkflowApplicationAbortedEventArgs)
                UpdateStatus($"Workflow Aborted. Exception: {e.Reason.GetType().FullName}{vbCrLf}{e.Reason.Message}")
            End Sub
    
        wfApp.OnUnhandledException = _
            Function(e As WorkflowApplicationUnhandledExceptionEventArgs)
                UpdateStatus($"Unhandled Exception: {e.UnhandledException.GetType().FullName}{vbCrLf}{e.UnhandledException.Message}")
                GameOver()
                Return UnhandledExceptionAction.Terminate
            End Function
    
        wfApp.PersistableIdle = _
            Function(e As WorkflowApplicationIdleEventArgs)
                ' Send the current WriteLine outputs to the status window.
                Dim writers = e.GetInstanceExtensions(Of StringWriter)()
                For Each writer In writers
                    UpdateStatus(writer.ToString())
                Next
                Return PersistableIdleAction.Unload
            End Function
    End Sub
    
    private void ConfigureWorkflowApplication(WorkflowApplication wfApp)
    {
        // Configure the persistence store.
        wfApp.InstanceStore = store;
    
        // Add a StringWriter to the extensions. This captures the output
        // from the WriteLine activities so we can display it in the form.
        var sw = new StringWriter();
        wfApp.Extensions.Add(sw);
    
        wfApp.Completed = delegate(WorkflowApplicationCompletedEventArgs e)
        {
            if (e.CompletionState == ActivityInstanceState.Faulted)
            {
                UpdateStatus($"Workflow Terminated. Exception: {e.TerminationException.GetType().FullName}\r\n{e.TerminationException.Message}");
            }
            else if (e.CompletionState == ActivityInstanceState.Canceled)
            {
                UpdateStatus("Workflow Canceled.");
            }
            else
            {
                int turns = Convert.ToInt32(e.Outputs["Turns"]);
                UpdateStatus($"Congratulations, you guessed the number in {turns} turns.");
            }
            GameOver();
        };
    
        wfApp.Aborted = delegate(WorkflowApplicationAbortedEventArgs e)
        {
            UpdateStatus($"Workflow Aborted. Exception: {e.Reason.GetType().FullName}\r\n{e.Reason.Message}");
        };
    
        wfApp.OnUnhandledException = delegate(WorkflowApplicationUnhandledExceptionEventArgs e)
        {
            UpdateStatus($"Unhandled Exception: {e.UnhandledException.GetType().FullName}\r\n{e.UnhandledException.Message}");
            GameOver();
            return UnhandledExceptionAction.Terminate;
        };
    
        wfApp.PersistableIdle = delegate(WorkflowApplicationIdleEventArgs e)
        {
            // Send the current WriteLine outputs to the status window.
            var writers = e.GetInstanceExtensions<StringWriter>();
            foreach (var writer in writers)
            {
                UpdateStatus(writer.ToString());
            }
            return PersistableIdleAction.Unload;
        };
    }
    

Starten en hervatten van meerdere werkstroomtypen inschakelen

Als u een werkstroomexemplaren wilt hervatten, moet de host de werkstroomdefinitie opgeven. In deze zelfstudie zijn er drie werkstroomtypen en in de volgende zelfstudiestappen worden meerdere versies van deze typen geïntroduceerd. WorkflowIdentity biedt een manier voor een hosttoepassing om identificatiegegevens te koppelen aan een persistent werkstroomexemplaren. De stappen in deze sectie laten zien hoe u een hulpprogrammaklasse maakt om u te helpen bij het toewijzen van de werkstroomidentiteit van een persistent werkstroomexemplaren aan de bijbehorende werkstroomdefinitie. Zie WorkflowIdentity en Versiebeheer gebruiken voor meer informatie over WorkflowIdentity en versiebeheer.

  1. Klik met de rechtermuisknop op NumberGuessWorkflowHost in Solution Explorer en kies Toevoegen, Klasse. Typ WorkflowVersionMap in het vak Naam en klik op Toevoegen.

  2. Voeg de volgende using of Imports instructies toe bovenaan het bestand met de andere using of Imports instructies.

    Imports System.Activities
    Imports NumberGuessWorkflowActivities
    
    using System.Activities;
    using NumberGuessWorkflowActivities;
    
  3. Vervang de WorkflowVersionMap klassedeclaratie door de volgende declaratie.

    Public Module WorkflowVersionMap
        Dim map As Dictionary(Of WorkflowIdentity, Activity)
    
        ' Current version identities.
        Public StateMachineNumberGuessIdentity As WorkflowIdentity
        Public FlowchartNumberGuessIdentity As WorkflowIdentity
        Public SequentialNumberGuessIdentity As WorkflowIdentity
    
        Sub New()
            map = New Dictionary(Of WorkflowIdentity, Activity)
    
            ' Add the current workflow version identities.
            StateMachineNumberGuessIdentity = New WorkflowIdentity With
            {
                .Name = "StateMachineNumberGuessWorkflow",
                .Version = New Version(1, 0, 0, 0)
            }
    
            FlowchartNumberGuessIdentity = New WorkflowIdentity With
            {
                .Name = "FlowchartNumberGuessWorkflow",
                .Version = New Version(1, 0, 0, 0)
            }
    
            SequentialNumberGuessIdentity = New WorkflowIdentity With
            {
                .Name = "SequentialNumberGuessWorkflow",
                .Version = New Version(1, 0, 0, 0)
            }
    
            map.Add(StateMachineNumberGuessIdentity, New StateMachineNumberGuessWorkflow())
            map.Add(FlowchartNumberGuessIdentity, New FlowchartNumberGuessWorkflow())
            map.Add(SequentialNumberGuessIdentity, New SequentialNumberGuessWorkflow())
        End Sub
    
        Public Function GetWorkflowDefinition(identity As WorkflowIdentity) As Activity
            Return map(identity)
        End Function
    
        Public Function GetIdentityDescription(identity As WorkflowIdentity) As String
            Return identity.ToString()
        End Function
    End Module
    
    public static class WorkflowVersionMap
    {
        static Dictionary<WorkflowIdentity, Activity> map;
    
        // Current version identities.
        static public WorkflowIdentity StateMachineNumberGuessIdentity;
        static public WorkflowIdentity FlowchartNumberGuessIdentity;
        static public WorkflowIdentity SequentialNumberGuessIdentity;
    
        static WorkflowVersionMap()
        {
            map = new Dictionary<WorkflowIdentity, Activity>();
    
            // Add the current workflow version identities.
            StateMachineNumberGuessIdentity = new WorkflowIdentity
            {
                Name = "StateMachineNumberGuessWorkflow",
                Version = new Version(1, 0, 0, 0)
            };
    
            FlowchartNumberGuessIdentity = new WorkflowIdentity
            {
                Name = "FlowchartNumberGuessWorkflow",
                Version = new Version(1, 0, 0, 0)
            };
    
            SequentialNumberGuessIdentity = new WorkflowIdentity
            {
                Name = "SequentialNumberGuessWorkflow",
                Version = new Version(1, 0, 0, 0)
            };
    
            map.Add(StateMachineNumberGuessIdentity, new StateMachineNumberGuessWorkflow());
            map.Add(FlowchartNumberGuessIdentity, new FlowchartNumberGuessWorkflow());
            map.Add(SequentialNumberGuessIdentity, new SequentialNumberGuessWorkflow());
        }
    
        public static Activity GetWorkflowDefinition(WorkflowIdentity identity)
        {
            return map[identity];
        }
    
        public static string GetIdentityDescription(WorkflowIdentity identity)
        {
            return identity.ToString();
       }
    }
    

    WorkflowVersionMap bevat drie werkstroomidentiteiten die zijn toegewezen aan de drie werkstroomdefinities uit deze zelfstudie en worden gebruikt in de volgende secties wanneer werkstromen worden gestart en hervat.

Een nieuwe werkstroom starten

  1. Voeg een Click handler toe voor NewGame. Als u de handler wilt toevoegen, schakelt u over naar de ontwerpweergave voor het formulier en dubbelklikt u erop NewGame. Er wordt een NewGame_Click handler toegevoegd en de weergave schakelt over naar de codeweergave voor het formulier. Wanneer de gebruiker op deze knop klikt, wordt er een nieuwe werkstroom gestart.

    Private Sub NewGame_Click(sender As Object, e As EventArgs) Handles NewGame.Click
    
    End Sub
    
    private void NewGame_Click(object sender, EventArgs e)
    {
    
    }
    
  2. Voeg de volgende code toe aan de klikhandler. Met deze code maakt u een woordenlijst met invoerargumenten voor de werkstroom, gesleuteld op argumentnaam. Deze woordenlijst bevat één vermelding die het bereik bevat van het willekeurig gegenereerde getal dat is opgehaald uit de keuzelijst met invoervak voor het bereik.

    Dim inputs As New Dictionary(Of String, Object)()
    inputs.Add("MaxNumber", Convert.ToInt32(NumberRange.SelectedItem))
    
    var inputs = new Dictionary<string, object>();
    inputs.Add("MaxNumber", Convert.ToInt32(NumberRange.SelectedItem));
    
  3. Voeg vervolgens de volgende code toe waarmee de werkstroom wordt gestart. De WorkflowIdentity definitie van de werkstroom en de werkstroom die overeenkomt met het type werkstroom dat is geselecteerd, worden opgehaald met behulp van de WorkflowVersionMap helperklasse. Vervolgens wordt een nieuw WorkflowApplication exemplaar gemaakt met behulp van de werkstroomdefinitie WorkflowIdentityen de woordenlijst met invoerargumenten.

    Dim identity As WorkflowIdentity = Nothing
    Select Case WorkflowType.SelectedItem.ToString()
        Case "SequentialNumberGuessWorkflow"
            identity = WorkflowVersionMap.SequentialNumberGuessIdentity
    
        Case "StateMachineNumberGuessWorkflow"
            identity = WorkflowVersionMap.StateMachineNumberGuessIdentity
    
        Case "FlowchartNumberGuessWorkflow"
            identity = WorkflowVersionMap.FlowchartNumberGuessIdentity
    End Select
    
    Dim wf As Activity = WorkflowVersionMap.GetWorkflowDefinition(identity)
    
    Dim wfApp = New WorkflowApplication(wf, inputs, identity)
    
    WorkflowIdentity identity = null;
    switch (WorkflowType.SelectedItem.ToString())
    {
        case "SequentialNumberGuessWorkflow":
            identity = WorkflowVersionMap.SequentialNumberGuessIdentity;
            break;
    
        case "StateMachineNumberGuessWorkflow":
            identity = WorkflowVersionMap.StateMachineNumberGuessIdentity;
            break;
    
        case "FlowchartNumberGuessWorkflow":
            identity = WorkflowVersionMap.FlowchartNumberGuessIdentity;
            break;
    };
    
    Activity wf = WorkflowVersionMap.GetWorkflowDefinition(identity);
    
    WorkflowApplication wfApp = new WorkflowApplication(wf, inputs, identity);
    
  4. Voeg vervolgens de volgende code toe waarmee de werkstroom wordt toegevoegd aan de lijst met werkstromen en de versiegegevens van de werkstroom op het formulier worden weergegeven.

    ' Add the workflow to the list and display the version information.
    workflowStarting = True
    InstanceId.SelectedIndex = InstanceId.Items.Add(wfApp.Id)
    WorkflowVersion.Text = identity.ToString()
    workflowStarting = False
    
    // Add the workflow to the list and display the version information.
    workflowStarting = true;
    InstanceId.SelectedIndex = InstanceId.Items.Add(wfApp.Id);
    WorkflowVersion.Text = identity.ToString();
    workflowStarting = false;
    
  5. Aanroep ConfigureWorkflowApplication voor het configureren van het exemplaararchief, extensies en werkstroomlevenscyclushandlers voor dit WorkflowApplication exemplaar.

    ' Configure the instance store, extensions, and
    ' workflow lifecycle handlers.
    ConfigureWorkflowApplication(wfApp)
    
    // Configure the instance store, extensions, and
    // workflow lifecycle handlers.
    ConfigureWorkflowApplication(wfApp);
    
  6. Bel ten slotte Run.

    ' Start the workflow.
    wfApp.Run()
    
    // Start the workflow.
    wfApp.Run();
    

    Het volgende voorbeeld is de voltooide NewGame_Click handler.

    Private Sub NewGame_Click(sender As Object, e As EventArgs) Handles NewGame.Click
        ' Start a new workflow.
        Dim inputs As New Dictionary(Of String, Object)()
        inputs.Add("MaxNumber", Convert.ToInt32(NumberRange.SelectedItem))
    
        Dim identity As WorkflowIdentity = Nothing
        Select Case WorkflowType.SelectedItem.ToString()
            Case "SequentialNumberGuessWorkflow"
                identity = WorkflowVersionMap.SequentialNumberGuessIdentity
    
            Case "StateMachineNumberGuessWorkflow"
                identity = WorkflowVersionMap.StateMachineNumberGuessIdentity
    
            Case "FlowchartNumberGuessWorkflow"
                identity = WorkflowVersionMap.FlowchartNumberGuessIdentity
        End Select
    
        Dim wf As Activity = WorkflowVersionMap.GetWorkflowDefinition(identity)
    
        Dim wfApp = New WorkflowApplication(wf, inputs, identity)
    
        ' Add the workflow to the list and display the version information.
        workflowStarting = True
        InstanceId.SelectedIndex = InstanceId.Items.Add(wfApp.Id)
        WorkflowVersion.Text = identity.ToString()
        workflowStarting = False
    
        ' Configure the instance store, extensions, and
        ' workflow lifecycle handlers.
        ConfigureWorkflowApplication(wfApp)
    
        ' Start the workflow.
        wfApp.Run()
    End Sub
    
    private void NewGame_Click(object sender, EventArgs e)
    {
        var inputs = new Dictionary<string, object>();
        inputs.Add("MaxNumber", Convert.ToInt32(NumberRange.SelectedItem));
    
        WorkflowIdentity identity = null;
        switch (WorkflowType.SelectedItem.ToString())
        {
            case "SequentialNumberGuessWorkflow":
                identity = WorkflowVersionMap.SequentialNumberGuessIdentity;
                break;
    
            case "StateMachineNumberGuessWorkflow":
                identity = WorkflowVersionMap.StateMachineNumberGuessIdentity;
                break;
    
            case "FlowchartNumberGuessWorkflow":
                identity = WorkflowVersionMap.FlowchartNumberGuessIdentity;
                break;
        };
    
        Activity wf = WorkflowVersionMap.GetWorkflowDefinition(identity);
    
        var wfApp = new WorkflowApplication(wf, inputs, identity);
    
        // Add the workflow to the list and display the version information.
        workflowStarting = true;
        InstanceId.SelectedIndex = InstanceId.Items.Add(wfApp.Id);
        WorkflowVersion.Text = identity.ToString();
        workflowStarting = false;
    
        // Configure the instance store, extensions, and
        // workflow lifecycle handlers.
        ConfigureWorkflowApplication(wfApp);
    
        // Start the workflow.
        wfApp.Run();
    }
    

Een werkstroom hervatten

  1. Voeg een Click handler toe voor EnterGuess. Als u de handler wilt toevoegen, schakelt u over naar de ontwerpweergave voor het formulier en dubbelklikt u erop EnterGuess. Wanneer de gebruiker op deze knop klikt, wordt een werkstroom hervat.

    Private Sub EnterGuess_Click(sender As Object, e As EventArgs) Handles EnterGuess.Click
    
    End Sub
    
    private void EnterGuess_Click(object sender, EventArgs e)
    {
    
    }
    
  2. Voeg de volgende code toe om ervoor te zorgen dat een werkstroom is geselecteerd in de lijst met werkstromen en of de schatting van de gebruiker geldig is.

    If WorkflowInstanceId = Guid.Empty Then
        MessageBox.Show("Please select a workflow.")
        Return
    End If
    
    Dim userGuess As Integer
    If Not Int32.TryParse(Guess.Text, userGuess) Then
        MessageBox.Show("Please enter an integer.")
        Guess.SelectAll()
        Guess.Focus()
        Return
    End If
    
    if (WorkflowInstanceId == Guid.Empty)
    {
        MessageBox.Show("Please select a workflow.");
        return;
    }
    
    int guess;
    if (!Int32.TryParse(Guess.Text, out guess))
    {
        MessageBox.Show("Please enter an integer.");
        Guess.SelectAll();
        Guess.Focus();
        return;
    }
    
  3. Haal vervolgens het WorkflowApplicationInstance persistente werkstroomexemplaren op. A WorkflowApplicationInstance vertegenwoordigt een persistent werkstroomexemplaar dat nog niet is gekoppeld aan een werkstroomdefinitie. De DefinitionIdentity van de WorkflowApplicationInstance bevat de WorkflowIdentity persistente werkstroominstantie. In deze zelfstudie wordt de WorkflowVersionMap hulpprogrammaklasse gebruikt om de WorkflowIdentity juiste werkstroomdefinitie toe te wijzen. Zodra de werkstroomdefinitie is opgehaald, wordt er een WorkflowApplication gemaakt met behulp van de juiste werkstroomdefinitie.

    Dim instance As WorkflowApplicationInstance = _
        WorkflowApplication.GetInstance(WorkflowInstanceId, store)
    
    ' Use the persisted WorkflowIdentity to retrieve the correct workflow
    ' definition from the dictionary.
    Dim wf As Activity = _
        WorkflowVersionMap.GetWorkflowDefinition(instance.DefinitionIdentity)
    
    ' Associate the WorkflowApplication with the correct definition
    Dim wfApp As New WorkflowApplication(wf, instance.DefinitionIdentity)
    
    WorkflowApplicationInstance instance =
        WorkflowApplication.GetInstance(WorkflowInstanceId, store);
    
    // Use the persisted WorkflowIdentity to retrieve the correct workflow
    // definition from the dictionary.
    Activity wf =
        WorkflowVersionMap.GetWorkflowDefinition(instance.DefinitionIdentity);
    
    // Associate the WorkflowApplication with the correct definition
    var wfApp = new WorkflowApplication(wf, instance.DefinitionIdentity);
    
  4. Zodra de app WorkflowApplication is gemaakt, configureert u het exemplaararchief, de werkstroomlevenscyclushandlers en -extensies door aan te roepen ConfigureWorkflowApplication. Deze stappen moeten worden uitgevoerd telkens wanneer er een nieuwe WorkflowApplication wordt gemaakt en moeten worden uitgevoerd voordat het werkstroomexemplaren in het WorkflowApplicationwerkstroomexemplaren worden geladen. Nadat de werkstroom is geladen, wordt deze hervat met de schatting van de gebruiker.

    ' Configure the extensions and lifecycle handlers.
    ' Do this before the instance is loaded. Once the instance is
    ' loaded it is too late to add extensions.
    ConfigureWorkflowApplication(wfApp)
    
    ' Load the workflow.
    wfApp.Load(instance)
    
    ' Resume the workflow.
    wfApp.ResumeBookmark("EnterGuess", userGuess)
    
    // Configure the extensions and lifecycle handlers.
    // Do this before the instance is loaded. Once the instance is
    // loaded it is too late to add extensions.
    ConfigureWorkflowApplication(wfApp);
    
    // Load the workflow.
    wfApp.Load(instance);
    
    // Resume the workflow.
    wfApp.ResumeBookmark("EnterGuess", guess);
    
  5. Ten slotte wist u het tekstvak voor schattingen en bereidt u het formulier voor om een andere schatting te accepteren.

    ' Clear the Guess textbox.
    Guess.Clear()
    Guess.Focus()
    
    // Clear the Guess textbox.
    Guess.Clear();
    Guess.Focus();
    

    Het volgende voorbeeld is de voltooide EnterGuess_Click handler.

    Private Sub EnterGuess_Click(sender As Object, e As EventArgs) Handles EnterGuess.Click
        If WorkflowInstanceId = Guid.Empty Then
            MessageBox.Show("Please select a workflow.")
            Return
        End If
    
        Dim userGuess As Integer
        If Not Int32.TryParse(Guess.Text, userGuess) Then
            MessageBox.Show("Please enter an integer.")
            Guess.SelectAll()
            Guess.Focus()
            Return
        End If
    
        Dim instance As WorkflowApplicationInstance = _
            WorkflowApplication.GetInstance(WorkflowInstanceId, store)
    
        ' Use the persisted WorkflowIdentity to retrieve the correct workflow
        ' definition from the dictionary.
        Dim wf As Activity = _
            WorkflowVersionMap.GetWorkflowDefinition(instance.DefinitionIdentity)
    
        ' Associate the WorkflowApplication with the correct definition
        Dim wfApp As New WorkflowApplication(wf, instance.DefinitionIdentity)
    
        ' Configure the extensions and lifecycle handlers.
        ' Do this before the instance is loaded. Once the instance is
        ' loaded it is too late to add extensions.
        ConfigureWorkflowApplication(wfApp)
    
        ' Load the workflow.
        wfApp.Load(instance)
    
        ' Resume the workflow.
        wfApp.ResumeBookmark("EnterGuess", userGuess)
    
        ' Clear the Guess textbox.
        Guess.Clear()
        Guess.Focus()
    End Sub
    
    private void EnterGuess_Click(object sender, EventArgs e)
    {
        if (WorkflowInstanceId == Guid.Empty)
        {
            MessageBox.Show("Please select a workflow.");
            return;
        }
    
        int guess;
        if (!Int32.TryParse(Guess.Text, out guess))
        {
            MessageBox.Show("Please enter an integer.");
            Guess.SelectAll();
            Guess.Focus();
            return;
        }
    
        WorkflowApplicationInstance instance =
            WorkflowApplication.GetInstance(WorkflowInstanceId, store);
    
        // Use the persisted WorkflowIdentity to retrieve the correct workflow
        // definition from the dictionary.
        Activity wf =
            WorkflowVersionMap.GetWorkflowDefinition(instance.DefinitionIdentity);
    
        // Associate the WorkflowApplication with the correct definition
        var wfApp = new WorkflowApplication(wf, instance.DefinitionIdentity);
    
        // Configure the extensions and lifecycle handlers.
        // Do this before the instance is loaded. Once the instance is
        // loaded it is too late to add extensions.
        ConfigureWorkflowApplication(wfApp);
    
        // Load the workflow.
        wfApp.Load(instance);
    
        // Resume the workflow.
        wfApp.ResumeBookmark("EnterGuess", guess);
    
        // Clear the Guess textbox.
        Guess.Clear();
        Guess.Focus();
    }
    

Een werkstroom beëindigen

  1. Voeg een Click handler toe voor QuitGame. Als u de handler wilt toevoegen, schakelt u over naar de ontwerpweergave voor het formulier en dubbelklikt u erop QuitGame. Wanneer de gebruiker op deze knop klikt, wordt de geselecteerde werkstroom beëindigd.

    Private Sub QuitGame_Click(sender As Object, e As EventArgs) Handles QuitGame.Click
    
    End Sub
    
    private void QuitGame_Click(object sender, EventArgs e)
    {
    
    }
    
  2. Voeg de volgende code toe aan de QuitGame_Click handler. Met deze code wordt eerst gecontroleerd of een werkstroom is geselecteerd in de lijst met werkstromen. Vervolgens wordt het persistente exemplaar in een WorkflowApplicationInstancegeladen, wordt de instantie gebruikt DefinitionIdentity om de juiste werkstroomdefinitie te bepalen en initialiseert u vervolgens de WorkflowApplication. Vervolgens worden de uitbreidingen en werkstroomlevenscyclushandlers geconfigureerd met een aanroep naar ConfigureWorkflowApplication. Zodra de WorkflowApplication configuratie is geconfigureerd, wordt deze geladen en vervolgens Terminate aangeroepen.

    If WorkflowInstanceId = Guid.Empty Then
        MessageBox.Show("Please select a workflow.")
        Return
    End If
    
    Dim instance As WorkflowApplicationInstance = _
        WorkflowApplication.GetInstance(WorkflowInstanceId, store)
    
    ' Use the persisted WorkflowIdentity to retrieve the correct workflow
    ' definition from the dictionary.
    Dim wf As Activity = WorkflowVersionMap.GetWorkflowDefinition(instance.DefinitionIdentity)
    
    ' Associate the WorkflowApplication with the correct definition.
    Dim wfApp As New WorkflowApplication(wf, instance.DefinitionIdentity)
    
    ' Configure the extensions and lifecycle handlers.
    ConfigureWorkflowApplication(wfApp)
    
    ' Load the workflow.
    wfApp.Load(instance)
    
    ' Terminate the workflow.
    wfApp.Terminate("User resigns.")
    
    if (WorkflowInstanceId == Guid.Empty)
    {
        MessageBox.Show("Please select a workflow.");
        return;
    }
    
    WorkflowApplicationInstance instance =
        WorkflowApplication.GetInstance(WorkflowInstanceId, store);
    
    // Use the persisted WorkflowIdentity to retrieve the correct workflow
    // definition from the dictionary.
    Activity wf = WorkflowVersionMap.GetWorkflowDefinition(instance.DefinitionIdentity);
    
    // Associate the WorkflowApplication with the correct definition
    var wfApp = new WorkflowApplication(wf, instance.DefinitionIdentity);
    
    // Configure the extensions and lifecycle handlers
    ConfigureWorkflowApplication(wfApp);
    
    // Load the workflow.
    wfApp.Load(instance);
    
    // Terminate the workflow.
    wfApp.Terminate("User resigns.");
    

De toepassing bouwen en uitvoeren

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

  2. Voeg de volgende using (of Imports) instructie toe boven aan het bestand met de andere using (of Imports) instructies.

    Imports System.Windows.Forms
    
    using System.Windows.Forms;
    
  3. Verwijder of markeer de bestaande werkstroomhostingcode uit Procedure: Voer een werkstroom uit en vervang deze door de volgende code.

    Sub Main()
        Application.EnableVisualStyles()
        Application.Run(New WorkflowHostForm())
    End Sub
    
    static void Main(string[] args)
    {
        Application.EnableVisualStyles();
        Application.Run(new WorkflowHostForm());
    }
    
  4. Klik met de rechtermuisknop op NumberGuessWorkflowHost in Solution Explorer en kies Eigenschappen. Geef op het tabblad Toepassing Windows-toepassing op voor het uitvoertype. Deze stap is optioneel, maar als het consolevenster niet wordt gevolgd, wordt naast het formulier weergegeven.

  5. Druk op Ctrl+Shift+B om de toepassing te bouwen.

  6. Zorg ervoor dat NumberGuessWorkflowHost is ingesteld als de opstarttoepassing en druk op Ctrl+F5 om de toepassing te starten.

  7. Selecteer een bereik voor het gokspel en het type werkstroom dat u wilt starten en klik op Nieuw spel. Voer een schatting in het vak Schatting in en klik op Ga om uw schatting in te dienen. De uitvoer van de WriteLine activiteiten wordt weergegeven in het formulier.

  8. Start verschillende werkstromen met verschillende werkstroomtypen en numerieke bereiken, voer enkele schattingen in en schakel tussen de werkstromen door een selectie te maken in de lijst Met werkstroomexemplaren .

    Wanneer u overschakelt naar een nieuwe werkstroom, worden de vorige schattingen en voortgang van de werkstroom niet weergegeven in het statusvenster. De reden waarom de status niet beschikbaar is, is omdat deze nergens wordt vastgelegd en opgeslagen. In de volgende stap van de zelfstudie, Procedure: Een aangepaste deelnemer voor bijhouden maken, maakt u een aangepaste traceringsdeelnemer die deze informatie opslaat.