Udostępnij za pośrednictwem


Jak utworzyć i uruchomić długotrwały przepływ pracy

Jedną z głównych funkcji programu Windows Workflow Foundation (WF) jest możliwość utrwalania i zwalniania bezczynnych przepływów pracy w bazie danych. Kroki opisane w temacie Instrukcje: Uruchamianie przepływu pracy przedstawiają podstawy hostingu przepływu pracy przy użyciu aplikacji konsolowej. Pokazano przykłady uruchamiania przepływów pracy, procedur obsługi cyklu życia przepływu pracy i wznawiania zakładek. Aby skutecznie zademonstrować trwałość przepływu pracy, wymagany jest bardziej złożony host przepływu pracy, który obsługuje uruchamianie i wznawianie wielu wystąpień przepływu pracy. W tym kroku w samouczku pokazano, jak utworzyć aplikację hosta formularzy systemu Windows, która obsługuje uruchamianie i wznawianie wielu wystąpień przepływu pracy, trwałość przepływu pracy i stanowi podstawę zaawansowanych funkcji, takich jak śledzenie i przechowywanie wersji, które przedstawiono w kolejnych krokach samouczka.

Uwaga

W tym kroku samouczka i kolejnych krokach są używane wszystkie trzy typy przepływów pracy z artykułu Instrukcje: Tworzenie przepływu pracy.

Aby utworzyć bazę danych trwałości

  1. Otwórz program SQL Server Management Studio i połącz się z serwerem lokalnym, na przykład .\SQLEXPRESS. Kliknij prawym przyciskiem myszy węzeł Bazy danych na serwerze lokalnym, a następnie wybierz pozycję Nowa baza danych. Nadaj nowej bazie danych nazwę WF45GettingStartedTutorial, zaakceptuj wszystkie inne wartości i wybierz przycisk OK.

    Uwaga

    Przed utworzeniem bazy danych upewnij się, że masz uprawnienie Utwórz bazę danych na serwerze lokalnym.

  2. Wybierz pozycję Otwórz, Plik z menu Plik . Przejdź do następującego folderu: C:\Windows\Microsoft.NET\Framework\v4.0.30319\sql\en

    Wybierz następujące dwa pliki i kliknij przycisk Otwórz.

    • SqlWorkflowInstanceStoreLogic.sql

    • SqlWorkflowInstanceStoreSchema.sql

  3. Wybierz SqlWorkflowInstanceStoreSchema.sql z menu Okno . Upewnij się, że na liście rozwijanej Dostępne bazy danych wybrano pozycję WF45GettingStartedTutorial i wybierz polecenie Wykonaj z menu Zapytanie.

  4. Wybierz SqlWorkflowInstanceStoreLogic.sql z menu Okno . Upewnij się, że na liście rozwijanej Dostępne bazy danych wybrano pozycję WF45GettingStartedTutorial i wybierz polecenie Wykonaj z menu Zapytanie.

    Ostrzeżenie

    Ważne jest, aby wykonać poprzednie dwa kroki w prawidłowej kolejności. Jeśli zapytania są wykonywane poza kolejnością, występują błędy, a baza danych trwałości nie jest poprawnie skonfigurowana.

Aby dodać odwołanie do zestawów DurableInstancing

  1. Kliknij prawym przyciskiem myszy pozycję NumberGuessWorkflowHost w Eksplorator rozwiązań i wybierz pozycję Dodaj odwołanie.

  2. Wybierz pozycję Zestawy z listy Dodaj odwołanie i wpisz DurableInstancing ciąg w polu Wyszukaj zestawy . Spowoduje to filtrowanie zestawów i ułatwia wybór żądanych odwołań.

  3. Zaznacz pole wyboru obok pozycji System.Activities.DurableInstancing i System.Runtime.DurableInstancing z listy Wyniki wyszukiwania, a następnie kliknij przycisk OK.

Aby utworzyć formularz hosta przepływu pracy

  1. Kliknij prawym przyciskiem myszy pozycję NumberGuessWorkflowHost w Eksplorator rozwiązań i wybierz pozycję Dodaj, Nowy element.

  2. Na liście Zainstalowane szablony wybierz pozycję Formularz systemu Windows, wpisz WorkflowHostForm w polu Nazwa, a następnie kliknij przycisk Dodaj.

  3. Skonfiguruj następujące właściwości w formularzu.

    Właściwości Wartość
    Formborderstyle Fixedsingle
    Maximizebox Fałsz
    Rozmiar 400, 420
  4. Dodaj następujące kontrolki do formularza w określonej kolejności i skonfiguruj właściwości zgodnie z instrukcjami.

    Kontrolka Właściwość: Wartość
    Przycisk Nazwa: NewGame

    Lokalizacja: 13, 13

    Rozmiar: 75, 23

    Tekst: Nowa gra
    Etykieta Lokalizacja: 94, 18

    Tekst: Odgadnij liczbę z zakresu od 1 do
    ComboBox Nazwa: NumberRange

    DropDownStyle: Lista rozwijana

    Elementy: 10, 100, 1000

    Lokalizacja: 228, 12

    Rozmiar: 143, 21
    Etykieta Lokalizacja: 13, 43

    Tekst: Typ przepływu pracy
    ComboBox Nazwa: WorkflowType

    DropDownStyle: Lista rozwijana

    Elementy: StateMachineNumberGuessWorkflow, FlowchartNumberGuessWorkflow, SequentialNumberGuessWorkflow

    Lokalizacja: 94, 40

    Rozmiar: 277, 21
    Etykieta Nazwa: WorkflowVersion

    Lokalizacja: 13, 362

    Tekst: wersja przepływu pracy
    GroupBox Lokalizacja: 13, 67

    Rozmiar: 358, 287

    Tekst: Gra

    Uwaga

    Podczas dodawania następujących kontrolek umieść je w polu GroupBox.

    Kontrolka Właściwość: Wartość
    Etykieta Lokalizacja: 7, 20

    Tekst: identyfikator wystąpienia przepływu pracy
    ComboBox Nazwa: InstanceId

    DropDownStyle: Lista rozwijana

    Lokalizacja: 121, 17

    Rozmiar: 227, 21
    Etykieta Lokalizacja: 7, 47

    Tekst: Zgadnij
    TextBox Nazwa: Odgadnij

    Lokalizacja: 50, 44

    Rozmiar: 65, 20
    Przycisk Nazwa: EnterGuess

    Lokalizacja: 121, 42

    Rozmiar: 75, 23

    Tekst: Wprowadź wartość Guess
    Przycisk Nazwa: QuitGame

    Lokalizacja: 274, 42

    Rozmiar: 75, 23

    Tekst: Zamknij
    TextBox Nazwa: WorkflowStatus

    Lokalizacja: 10, 73

    Wielowierszowa: prawda

    ReadOnly: Prawda

    Paski przewijania: pionowy

    Rozmiar: 338, 208
  5. Ustaw właściwość AcceptButton formularza na EnterGuess.

Poniższy przykład ilustruje wypełniony formularz.

Screenshot of a Windows Workflow Foundation Workflow Host Form.

Aby dodać właściwości i metody pomocnicze formularza

Kroki opisane w tej sekcji dodają właściwości i metody pomocnicze do klasy formularzy, które konfigurują interfejs użytkownika formularza w celu obsługi uruchamiania i wznawiania przepływów pracy zgadywania liczb.

  1. Kliknij prawym przyciskiem myszy pozycję WorkflowHostForm w Eksplorator rozwiązań i wybierz polecenie Wyświetl kod.

  2. Dodaj następujące using instrukcje (lub Imports) w górnej części pliku z innymi using instrukcjami (lub Imports).

    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. Dodaj następujące deklaracje składowe do klasy WorkflowHostForm .

    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;
    

    Uwaga

    Jeśli parametry połączenia jest inna, zaktualizuj jąconnectionString, aby odwołać się do bazy danych.

  4. WorkflowInstanceId Dodaj właściwość do WorkflowFormHost klasy.

    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;
        }
    }
    

    W InstanceId polu kombi zostanie wyświetlona lista identyfikatorów utrwalonego wystąpienia przepływu pracy, a WorkflowInstanceId właściwość zwraca aktualnie wybrany przepływ pracy.

  5. Dodaj procedurę obsługi dla zdarzenia formularza Load . Aby dodać procedurę obsługi, przejdź do widoku projektu dla formularza, kliknij ikonę Zdarzenia w górnej części okna Właściwości , a następnie kliknij dwukrotnie pozycję Załaduj.

    Private Sub WorkflowHostForm_Load(sender As Object, e As EventArgs) Handles Me.Load
    
    End Sub
    
    private void WorkflowHostForm_Load(object sender, EventArgs e)
    {
    
    }
    
  6. Dodaj następujący kod do pliku 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();
    

    Po załadowaniu SqlWorkflowInstanceStore formularza zostanie skonfigurowane pola kombi zakresu i typu przepływu pracy są ustawione na wartości domyślne, a utrwalone wystąpienia przepływu pracy są dodawane do InstanceId pola kombi.

  7. Dodaj procedurę SelectedIndexChanged obsługi dla elementu InstanceId. Aby dodać procedurę obsługi, przejdź do widoku projektu dla formularza, zaznacz InstanceId pole kombi, kliknij ikonę Zdarzenia w górnej części okna Właściwości , a następnie kliknij dwukrotnie polecenie 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. Dodaj następujący kod do pliku InstanceId_SelectedIndexChanged. Za każdym razem, gdy użytkownik wybierze przepływ pracy przy użyciu pola kombi, program obsługi aktualizuje okno stanu.

    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. Dodaj następującą ListPersistedWorkflows metodę do klasy formularza.

    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 wysyła zapytanie do magazynu wystąpień utrwalonego przepływu pracy i dodaje identyfikatory wystąpień do cboInstanceId pola kombi.

  10. Dodaj następującą UpdateStatus metodę i odpowiedni delegat do klasy formularza. Ta metoda aktualizuje okno stanu w formularzu ze stanem aktualnie uruchomionego przepływu pracy.

    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. Dodaj następującą GameOver metodę i odpowiedni delegat do klasy formularza. Po zakończeniu przepływu pracy ta metoda aktualizuje interfejs użytkownika formularza, usuwając identyfikator wystąpienia ukończonego przepływu pracy z pola kombi InstanceId .

    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;
        }
    }
    

Aby skonfigurować magazyn wystąpień, programy obsługi cyklu życia przepływu pracy i rozszerzenia

  1. Dodaj metodę ConfigureWorkflowApplication do klasy formularza.

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

    Ta metoda konfiguruje WorkflowApplicationelement , dodaje żądane rozszerzenia i dodaje programy obsługi dla zdarzeń cyklu życia przepływu pracy.

  2. W ConfigureWorkflowApplicationpliku określ wartość SqlWorkflowInstanceStore dla elementu WorkflowApplication.

    ' Configure the persistence store.
    wfApp.InstanceStore = store
    
    // Configure the persistence store.
    wfApp.InstanceStore = store;
    
  3. Następnie utwórz StringWriter wystąpienie i dodaj je do Extensions kolekcji .WorkflowApplication Po dodaniu elementu StringWriter do rozszerzeń przechwytuje wszystkie WriteLine dane wyjściowe działania. Gdy przepływ pracy stanie się bezczynny, WriteLine dane wyjściowe można wyodrębnić z StringWriter elementu i wyświetlanego w formularzu.

    ' 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. Dodaj następującą procedurę Completed obsługi dla zdarzenia. Po pomyślnym zakończeniu przepływu pracy liczba zmieni się, aby odgadnąć, że liczba zostanie wyświetlona w oknie stanu. Jeśli przepływ pracy zakończy się, zostaną wyświetlone informacje o wyjątku, które spowodowały zakończenie. Na końcu procedury obsługi wywoływana GameOver jest metoda, która usuwa ukończony przepływ pracy z listy przepływów pracy.

    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. Dodaj następujące Aborted programy obsługi i OnUnhandledException . Metoda GameOver nie jest wywoływana z Aborted programu obsługi, ponieważ po przerwaniu wystąpienia przepływu pracy nie zostanie przerwane i można wznowić wystąpienie w późniejszym czasie.

    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. Dodaj następującą PersistableIdle procedurę obsługi. Ta procedura obsługi pobiera StringWriter dodane rozszerzenie, wyodrębnia dane wyjściowe z WriteLine działań i wyświetla je w oknie stanu.

    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;
    };
    

    Wyliczenie PersistableIdleAction ma trzy wartości: None, Persisti Unload. Persist powoduje, że przepływ pracy będzie się powtarzać, ale nie powoduje zwolnienia przepływu pracy. Unload powoduje utrwalanie i zwalnianie przepływu pracy.

    Poniższy przykład to ukończona ConfigureWorkflowApplication metoda.

    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;
        };
    }
    

Aby włączyć uruchamianie i wznawianie wielu typów przepływów pracy

Aby wznowić wystąpienie przepływu pracy, host musi podać definicję przepływu pracy. W tym samouczku istnieją trzy typy przepływów pracy, a kolejne kroki samouczka przedstawiają wiele wersji tego typu. WorkflowIdentity program umożliwia aplikacji hosta skojarzenie informacji identyfikujących z utrwalonego wystąpienia przepływu pracy. W krokach w tej sekcji pokazano, jak utworzyć klasę narzędzi, aby ułatwić mapowanie tożsamości przepływu pracy z utrwalonego wystąpienia przepływu pracy na odpowiednią definicję przepływu pracy. Aby uzyskać więcej informacji na temat WorkflowIdentity i przechowywania wersji, zobacz Using WorkflowIdentity and Versioning (Używanie identyfikatorów przepływu pracy i przechowywania wersji).

  1. Kliknij prawym przyciskiem myszy pozycję NumberGuessWorkflowHost w Eksplorator rozwiązań i wybierz polecenie Dodaj, Klasa. Wpisz WorkflowVersionMap w polu Nazwa i kliknij przycisk Dodaj.

  2. Dodaj następujące using instrukcje lub Imports w górnej części pliku z innymi using instrukcjami lub Imports .

    Imports System.Activities
    Imports NumberGuessWorkflowActivities
    
    using System.Activities;
    using NumberGuessWorkflowActivities;
    
  3. Zastąp deklarację WorkflowVersionMap klasy następującą deklaracją.

    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 Zawiera trzy tożsamości przepływu pracy, które są mapowane na trzy definicje przepływu pracy z tego samouczka i są używane w poniższych sekcjach, gdy przepływy pracy są uruchamiane i wznawiane.

Aby uruchomić nowy przepływ pracy

  1. Dodaj procedurę Click obsługi dla elementu NewGame. Aby dodać procedurę obsługi, przejdź do widoku projektu dla formularza, a następnie kliknij dwukrotnie pozycję NewGame. Dodano procedurę NewGame_Click obsługi, a widok przełącza się do widoku kodu dla formularza. Za każdym razem, gdy użytkownik kliknie ten przycisk, zostanie uruchomiony nowy przepływ pracy.

    Private Sub NewGame_Click(sender As Object, e As EventArgs) Handles NewGame.Click
    
    End Sub
    
    private void NewGame_Click(object sender, EventArgs e)
    {
    
    }
    
  2. Dodaj następujący kod do procedury obsługi kliknięć. Ten kod tworzy słownik argumentów wejściowych dla przepływu pracy, do których kluczem jest nazwa argumentu. Ten słownik zawiera jeden wpis zawierający zakres losowo wygenerowanej liczby pobranej z pola kombi zakresu.

    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. Następnie dodaj następujący kod, który uruchamia przepływ pracy. Definicja WorkflowIdentity przepływu pracy i odpowiadająca wybranemu WorkflowVersionMap typowi przepływu pracy jest pobierana przy użyciu klasy pomocnika. Następnie zostanie utworzone nowe WorkflowApplication wystąpienie przy użyciu definicji przepływu pracy, WorkflowIdentityi słownika argumentów wejściowych.

    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. Następnie dodaj następujący kod, który dodaje przepływ pracy do listy przepływów pracy i wyświetla informacje o wersji przepływu pracy w formularzu.

    ' 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. Wywołaj metodę ConfigureWorkflowApplication konfigurowania magazynu wystąpień, rozszerzeń i procedur obsługi cyklu życia przepływu pracy dla tego WorkflowApplication wystąpienia.

    ' Configure the instance store, extensions, and
    ' workflow lifecycle handlers.
    ConfigureWorkflowApplication(wfApp)
    
    // Configure the instance store, extensions, and
    // workflow lifecycle handlers.
    ConfigureWorkflowApplication(wfApp);
    
  6. Na koniec wywołaj metodę Run.

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

    Poniższy przykład to ukończona NewGame_Click procedura obsługi.

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

Aby wznowić przepływ pracy

  1. Dodaj procedurę Click obsługi dla elementu EnterGuess. Aby dodać procedurę obsługi, przejdź do widoku projektu dla formularza, a następnie kliknij dwukrotnie pozycję EnterGuess. Za każdym razem, gdy użytkownik kliknie ten przycisk, zostanie wznowiony przepływ pracy.

    Private Sub EnterGuess_Click(sender As Object, e As EventArgs) Handles EnterGuess.Click
    
    End Sub
    
    private void EnterGuess_Click(object sender, EventArgs e)
    {
    
    }
    
  2. Dodaj następujący kod, aby upewnić się, że przepływ pracy został wybrany na liście przepływów pracy i czy odgadnięcie użytkownika jest prawidłowe.

    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. Następnie pobierz WorkflowApplicationInstance utrwalone wystąpienie przepływu pracy. Obiekt WorkflowApplicationInstance reprezentuje utrwalone wystąpienie przepływu pracy, które nie zostało jeszcze skojarzone z definicją przepływu pracy. Element DefinitionIdentity zawiera WorkflowApplicationInstanceWorkflowIdentity wystąpienie utrwalonego przepływu pracy. W tym samouczku WorkflowVersionMap klasa narzędzia jest używana do mapowania elementu WorkflowIdentity na poprawną definicję przepływu pracy. Po pobraniu WorkflowApplication definicji przepływu pracy zostanie utworzona wartość , używając poprawnej definicji przepływu pracy.

    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. Po utworzeniu WorkflowApplication programu skonfiguruj magazyn wystąpień, programy obsługi cyklu życia przepływu pracy i rozszerzenia, wywołując metodę ConfigureWorkflowApplication. Te kroki należy wykonać za każdym razem, gdy zostanie utworzony nowy WorkflowApplication , i należy je wykonać przed załadowaniem wystąpienia przepływu pracy do klasy WorkflowApplication. Po załadowaniu przepływu pracy zostanie wznowiony zgadywaniem użytkownika.

    ' 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. Na koniec wyczyść pole tekstowe zgadywania i przygotuj formularz do zaakceptowania innego zgadnięcia.

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

    Poniższy przykład to ukończona EnterGuess_Click procedura obsługi.

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

Aby zakończyć przepływ pracy

  1. Dodaj procedurę Click obsługi dla elementu QuitGame. Aby dodać procedurę obsługi, przejdź do widoku projektu dla formularza, a następnie kliknij dwukrotnie pozycję QuitGame. Za każdym razem, gdy użytkownik kliknie ten przycisk, aktualnie wybrany przepływ pracy zostanie zakończony.

    Private Sub QuitGame_Click(sender As Object, e As EventArgs) Handles QuitGame.Click
    
    End Sub
    
    private void QuitGame_Click(object sender, EventArgs e)
    {
    
    }
    
  2. Dodaj następujący kod do QuitGame_Click programu obsługi. Ten kod najpierw sprawdza, czy na liście przepływów pracy wybrano przepływ pracy. Następnie ładuje utrwalone wystąpienie do WorkflowApplicationInstanceklasy , używa DefinitionIdentity elementu , aby określić poprawną definicję przepływu pracy, a następnie inicjuje WorkflowApplicationelement . Następnie rozszerzenia i procedury obsługi cyklu życia przepływu pracy są konfigurowane za pomocą wywołania metody ConfigureWorkflowApplication. Po skonfigurowaniu WorkflowApplication jest ładowana, a następnie Terminate wywoływana.

    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.");
    

Aby skompilować i uruchomić aplikację

  1. Kliknij dwukrotnie Program.cs (lub Module1.vb) w Eksplorator rozwiązań, aby wyświetlić kod.

  2. Dodaj następującą using instrukcję (lub Imports) w górnej części pliku z innymi using instrukcjami (lub Imports).

    Imports System.Windows.Forms
    
    using System.Windows.Forms;
    
  3. Usuń istniejący kod hostingu przepływu pracy lub oznacz go jako komentarz z sekcji Instrukcje: Uruchamianie przepływu pracy i zastąp go następującym kodem.

    Sub Main()
        Application.EnableVisualStyles()
        Application.Run(New WorkflowHostForm())
    End Sub
    
    static void Main(string[] args)
    {
        Application.EnableVisualStyles();
        Application.Run(new WorkflowHostForm());
    }
    
  4. Kliknij prawym przyciskiem myszy pozycję NumberGuessWorkflowHost w Eksplorator rozwiązań i wybierz polecenie Właściwości. Na karcie Aplikacja określ wartość Aplikacja systemu Windows dla typu dane wyjściowe. Ten krok jest opcjonalny, ale jeśli nie jest on obserwowany, okno konsoli jest wyświetlane oprócz formularza.

  5. Naciśnij klawisze Ctrl+Shift+B, aby skompilować aplikację.

  6. Upewnij się, że parametr NumberGuessWorkflowHost jest ustawiony jako aplikacja startowa, a następnie naciśnij klawisze Ctrl+F5, aby uruchomić aplikację.

  7. Wybierz zakres dla gry zgadywania i typu przepływu pracy do uruchomienia, a następnie kliknij pozycję Nowa gra. Wprowadź wartość zgadnij w polu Odgadnij i kliknij przycisk Przejdź, aby przesłać swoje odgadnięcie. Zwróć uwagę, że dane wyjściowe z WriteLine działań są wyświetlane w formularzu.

  8. Uruchom kilka przepływów pracy przy użyciu różnych typów przepływów pracy i zakresów liczb, wprowadź pewne odgadnięcia i przełącz się między przepływami pracy, wybierając z listy Identyfikator wystąpienia przepływu pracy.

    Pamiętaj, że po przełączeniu się do nowego przepływu pracy poprzednie odgadnięcia i postęp przepływu pracy nie są wyświetlane w oknie stanu. Przyczyną niedostępnego stanu jest to, że nie jest przechwytywany i zapisywany w dowolnym miejscu. W następnym kroku samouczka , Jak utworzyć uczestnika niestandardowego śledzenia, utworzysz niestandardowego uczestnika śledzenia, który zapisuje te informacje.