Bagikan melalui


Cara membuat dan menjalankan alur kerja yang berjalan lama

Salah satu fitur utama dari Windows Workflow Foundation (WF) adalah kemampuan runtime untuk bertahan dan membongkar alur kerja yang menganggur ke database. Langkah-langkah dalam Cara: Menjalankan Alur Kerja menunjukkan dasar-dasar hosting alur kerja menggunakan aplikasi konsol. Contoh ditunjukkan alur kerja awal, penangan siklus hidup alur kerja, dan melanjutkan bookmark. Untuk mendemonstrasikan ketekunan alur kerja secara efektif, host alur kerja yang lebih kompleks diperlukan yang mendukung memulai dan melanjutkan beberapa instans alur kerja. Langkah dalam tutorial ini menunjukkan cara membuat aplikasi host formulir Windows yang mendukung memulai dan melanjutkan beberapa instans alur kerja, ketekunan alur kerja, dan menyediakan dasar untuk fitur lanjutan seperti pelacakan dan pembuatan versi yang ditunjukkan dalam langkah tutorial berikutnya.

Catatan

Langkah tutorial ini dan langkah-langkah selanjutnya menggunakan ketiga jenis alur kerja dari Cara: Membuat Alur Kerja.

Untuk membuat database persistensi

  1. Buka SQL Server Management Studio dan hubungkan ke server lokal, misalnya .\SQLEXPRESS. Klik kanan node Databases di server lokal, dan pilih Database Baru. Beri nama database baru WF45GettingStartedTutorial, terima semua nilai lainnya, dan pilih OK.

    Catatan

    Pastikan Anda memiliki izin Buat Database di server lokal sebelum membuat database.

  2. Pilih Buka, File dari menu File. Jelajahi folder berikut: C:\Windows\Microsoft.NET\Framework\v4.0.30319\sql\en

    Pilih dua file berikut dan klik Buka.

    • SqlWorkflowInstanceStoreLogic.sql

    • SqlWorkflowInstanceStoreSchema.sql

  3. Pilih SqlWorkflowInstanceStoreSchema.sql dari menu Jendela. Pastikan bahwa WF45GettingStartedTutorial dipilih di menu dropdown Database yang Tersedia dan pilih Eksekusi dari menu Kueri.

  4. Pilih SqlWorkflowInstanceStoreLogic.sql dari menu Jendela. Pastikan bahwa WF45GettingStartedTutorial dipilih di menu dropdown Database yang Tersedia dan pilih Eksekusi dari menu Kueri.

    Peringatan

    Penting untuk melakukan dua langkah sebelumnya dalam urutan yang benar. Jika kueri dijalankan tidak sesuai urutan, kesalahan terjadi dan database persistensi tidak dikonfigurasi dengan benar.

Untuk menambahkan referensi ke rakitan DurableInstancing

  1. Klik kanan NumberGuessWorkflowHost di Penjelajah Solusi dan pilih Tambahkan Referensi.

  2. Pilih Rakitan dari daftar Tambahkan Referensi, dan ketik DurableInstancing ke dalam kotak Cari Rakitan. Tindakan ini akan menyaring rakitan dan membuat referensi yang diinginkan lebih mudah untuk dipilih.

  3. Centang kotak di samping System.Activities.DurableInstancing dan System.Runtime.DurableInstancing dari daftar Hasil Pencarian, dan klik OK.

Untuk membuat formulir host alur kerja

  1. Klik kanan NumberGuessWorkflowHost di Penjelajah Solusi dan pilih Tambahkan, Item Baru.

  2. Di daftar template Terinstal, pilih Formulir Windows, ketik WorkflowHostForm di kotak Nama, dan klik Tambahkan.

  3. Konfigurasikan properti berikut pada formulir.

    Properti Nilai
    FormBorderStyle FixedSingle
    MaximizeBox Salah
    Ukuran 400, 420
  4. Tambahkan kontrol berikut ke formulir dalam urutan yang ditentukan dan konfigurasikan properti seperti yang diarahkan.

    Menguasai Property: Nilai
    Tombol Nama: NewGame

    Lokasi: 13, 13

    Ukuran: 75, 23

    Teks: Game Baru
    Label Lokasi: 94, 18

    Teks: Tebak angka dari 1 hingga
    ComboBox Nama: NumberRange

    DropDownStyle: DropDownList

    Item: 10, 100, 1000

    Lokasi: 228, 12

    Ukuran: 143, 21
    Label Lokasi: 13, 43

    Teks: Jenis alur kerja
    ComboBox Nama: Jenis Alur Kerja

    DropDownStyle: DropDownList

    Item: StateMachineNumberGuessWorkflow, FlowchartNumberGuessWorkflow, SequentialNumberGuessWorkflow

    Lokasi: 94, 40

    Ukuran: 277, 21
    Label Nama: WorkflowVersion

    Lokasi: 13, 362

    Teks: Versi alur kerja
    GroupBox Lokasi: 13, 67

    Ukuran: 358, 287

    Teks: Permainan

    Catatan

    Saat menambahkan kontrol berikut, masukkan ke dalam GroupBox.

    Menguasai Property: Nilai
    Label Lokasi: 7, 20

    Teks: ID Instans Alur Kerja
    ComboBox Nama: InstanceId

    DropDownStyle: DropDownList

    Lokasi: 121, 17

    Ukuran: 227, 21
    Label Lokasi: 7, 47

    Teks: Tebak
    Textbox Nama: Tebak

    Lokasi: 50, 44

    Ukuran: 65, 20
    Tombol Nama: EnterGuess

    Lokasi: 121, 42

    Ukuran: 75, 23

    Teks: Masukkan Tebakan
    Tombol Nama: QuitGame

    Lokasi: 274, 42

    Ukuran: 75, 23

    Teks: Keluar
    Textbox Nama: WorkflowStatus

    Lokasi: 10, 73

    Multiline: Benar

    ReadOnly: True

    ScrollBars: Vertikal

    Ukuran: 338, 208
  5. Atur properti AcceptButton formulir ke EnterGuess.

Contoh berikut mengilustrasikan formulir yang telah diisi.

Screenshot of a Windows Workflow Foundation Workflow Host Form.

Untuk menambahkan properti dan metode pembantu dari formulir

Langkah-langkah di bagian ini menambahkan properti dan metode pembantu ke kelas formulir yang mengonfigurasi UI formulir untuk mendukung menjalankan dan melanjutkan alur kerja tebakan angka.

  1. Klik kanan WorkflowHostForm di Penjelajah Solusi dan pilih Lihat Kode.

  2. Tambahkan pernyataan using (atau Imports) berikut di bagian atas file dengan pernyataan using (atau Imports) lainnya.

    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. Tambahkan deklarasi anggota berikut ke kelas 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;
    

    Catatan

    Jika string koneksi Anda berbeda, perbarui connectionString untuk mereferensikan ke database Anda.

  4. Tambahkan properti WorkflowInstanceId ke kelas WorkflowFormHost.

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

    Kotak kombo InstanceId menampilkan daftar id instans alur kerja yang bertahan, dan properti WorkflowInstanceId mengembalikan alur kerja yang dipilih saat ini.

  5. Tambahkan penangan untuk peristiwa Load formulir. Untuk menambahkan penangan, alihkan ke Tampilan Desain untuk formulir, klik ikon Peristiwa di bagian atas jendela Properti, dan klik dua kali Muat.

    Private Sub WorkflowHostForm_Load(sender As Object, e As EventArgs) Handles Me.Load
    
    End Sub
    
    private void WorkflowHostForm_Load(object sender, EventArgs e)
    {
    
    }
    
  6. Tambahkan kode berikut ke 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();
    

    Saat formulir dimuat, SqlWorkflowInstanceStore dikonfigurasi, kotak kombo rentang dan jenis alur kerja diatur ke nilai default, dan instans alur kerja yang bertahan ditambahkan ke kotak kombo InstanceId.

  7. Tambahkan penangan SelectedIndexChanged untuk InstanceId. Untuk menambahkan penangan, alihkan ke Tampilan Desain untuk formulir, pilih InstanceId kotak kombo, klik ikon Peristiwa di bagian atas jendela Properti, dan klik dua kali 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. Tambahkan kode berikut ke InstanceId_SelectedIndexChanged. Setiap kali pengguna memilih alur kerja dengan menggunakan kotak kombo, penangan ini memperbarui jendela status.

    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. Tambahkan metode ListPersistedWorkflows berikut ke kelas formulir.

    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 mengkueri penyimpanan instans untuk instans alur kerja yang bertahan, dan menambahkan id instans ke kotak kombo cboInstanceId.

  10. Tambahkan metode UpdateStatus berikut dan delegasi yang sesuai ke kelas formulir. Metode ini memperbarui jendela status pada formulir dengan status alur kerja yang sedang berjalan.

    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. Tambahkan metode GameOver berikut dan delegasi yang sesuai ke kelas formulir. Ketika alur kerja selesai, metode ini memperbarui UI formulir dengan menghapus id instans alur kerja yang diselesaikan dari kotak kombo 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;
        }
    }
    

Untuk mengonfigurasi penyimpanan instans, penangan siklus hidup alur kerja, dan ekstensi

  1. Tambahkan metode ConfigureWorkflowApplication ke kelas formulir.

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

    Metode ini mengonfigurasi WorkflowApplication, menambahkan ekstensi yang diinginkan, dan menambahkan penangan untuk peristiwa siklus hidup alur kerja.

  2. Di ConfigureWorkflowApplication, tentukan SqlWorkflowInstanceStore untuk WorkflowApplication.

    ' Configure the persistence store.
    wfApp.InstanceStore = store
    
    // Configure the persistence store.
    wfApp.InstanceStore = store;
    
  3. Selanjutnya, buat instans StringWriter dan tambahkan ke kumpulan Extensions dari WorkflowApplication. Saat StringWriter ditambahkan ke ekstensi, ia menangkap semua output aktivitas WriteLine. Saat alur kerja menjadi tidak aktif, output WriteLine dapat diekstraksi dari StringWriter dan ditampilkan pada formulir.

    ' 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. Tambahkan penangan berikut untuk peristiwa Completed. Ketika alur kerja berhasil diselesaikan, jumlah giliran yang diambil untuk menebak nomor ditampilkan ke jendela status. Jika alur kerja berakhir, informasi pengecualian yang menyebabkan penghentian akan ditampilkan. Di akhir penangan, metode GameOver dipanggil, yang menghapus alur kerja yang sudah selesai dari daftar alur kerja.

    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. Tambahkan penangan Aborted dan OnUnhandledException berikut. Metode GameOver tidak dipanggil dari penangan Aborted karena ketika instans alur kerja dibatalkan, metode tidak dihentikan, dan dimungkinkan untuk melanjutkan instans di lain waktu.

    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. Tambahkan penangan PersistableIdle berikut. Penangan ini mengambil ekstensi StringWriter yang telah ditambahkan, mengekstrak output dari aktivitas WriteLine, dan menampilkannya di jendela status.

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

    Enumerasi PersistableIdleAction memiliki tiga nilai: None, Persist, dan Unload. Persist menyebabkan alur kerja bertahan tetapi tidak menyebabkan alur kerja dibongkar. Unload menyebabkan alur kerja bertahan dan dibongkar.

    Contoh berikut adalah metode ConfigureWorkflowApplication yang telah selesai.

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

Untuk mengaktifkan memulai dan melanjutkan beberapa jenis alur kerja

Untuk melanjutkan instans alur kerja, host harus memberikan definisi alur kerja. Dalam tutorial ini ada tiga jenis alur kerja, dan langkah-langkah tutorial selanjutnya akan memperkenalkan beberapa versi jenis ini. WorkflowIdentity menyediakan cara bagi aplikasi host untuk mengaitkan informasi pengidentifikasi dengan instans alur kerja yang bertahan. Langkah-langkah di bagian ini menunjukkan cara membuat kelas utilitas guna membantu memetakan identitas alur kerja dari instans alur kerja yang bertahan ke definisi alur kerja yang sesuai. Untuk informasi selengkapnya tentang WorkflowIdentity dan pembuatan versi, lihat Menggunakan WorkflowIdentity dan Versioning.

  1. Klik kanan NumberGuessWorkflowHost di Penjelajah Solusi dan pilih Tambahkan, Kelas. Ketik WorkflowVersionMap ke dalam kotak Nama, lalu klik Tambahkan.

  2. Tambahkan pernyataan using atau Imports berikut di bagian atas file dengan pernyataan using atau Imports lainnya.

    Imports System.Activities
    Imports NumberGuessWorkflowActivities
    
    using System.Activities;
    using NumberGuessWorkflowActivities;
    
  3. Ganti deklarasi kelas WorkflowVersionMap dengan deklarasi berikut.

    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 berisi tiga identitas alur kerja yang dipetakan ke tiga definisi alur kerja dari tutorial ini dan digunakan di bagian berikut saat alur kerja dimulai dan dilanjutkan.

Untuk memulai alur kerja baru

  1. Tambahkan penangan Click untuk NewGame. Untuk menambahkan penangan, alihkan ke Tampilan Desain untuk formulir, dan klik dua kali NewGame. Penangan NewGame_Click ditambahkan dan tampilan beralih ke tampilan kode untuk formulir. Setiap kali pengguna mengeklik tombol ini, alur kerja baru dimulai.

    Private Sub NewGame_Click(sender As Object, e As EventArgs) Handles NewGame.Click
    
    End Sub
    
    private void NewGame_Click(object sender, EventArgs e)
    {
    
    }
    
  2. Tambahkan kode berikut ke penangan klik. Kode ini membuat kamus argumen input untuk alur kerja, dikunci dengan nama argumen. Kamus ini memiliki satu entri yang berisi rentang angka yang dihasilkan secara acak yang diambil dari kotak kombo rentang.

    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. Selanjutnya, tambahkan kode berikut yang memulai alur kerja. WorkflowIdentity dan definisi alur kerja yang sesuai dengan jenis alur kerja yang dipilih diambil menggunakan kelas pembantu WorkflowVersionMap. Selanjutnya, instans WorkflowApplication baru dibuat menggunakan definisi alur kerja, WorkflowIdentity, dan kamus argumen input.

    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. Selanjutnya, tambahkan kode berikut yang menambahkan alur kerja ke daftar alur kerja dan menampilkan informasi versi alur kerja pada formulir.

    ' 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. Panggil ConfigureWorkflowApplication untuk mengonfigurasi penyimpanan instans, ekstensi, dan penangan siklus hidup alur kerja untuk instans WorkflowApplication ini.

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

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

    Contoh berikut adalah penangan NewGame_Click yang telah selesai.

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

Untuk melanjutkan alur kerja

  1. Tambahkan penangan Click untuk EnterGuess. Untuk menambahkan penangan, alihkan ke Tampilan Desain untuk formulir, dan klik dua kali EnterGuess. Setiap kali pengguna mengeklik tombol ini, alur kerja dilanjutkan.

    Private Sub EnterGuess_Click(sender As Object, e As EventArgs) Handles EnterGuess.Click
    
    End Sub
    
    private void EnterGuess_Click(object sender, EventArgs e)
    {
    
    }
    
  2. Tambahkan kode berikut untuk memastikan bahwa alur kerja dipilih dalam daftar alur kerja, dan tebakan pengguna valid.

    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. Selanjutnya, ambil WorkflowApplicationInstance dari instans alur kerja yang bertahan. WorkflowApplicationInstance mewakili instans alur kerja yang bertahan yang belum dikaitkan dengan definisi alur kerja. DefinitionIdentity dari WorkflowApplicationInstance berisi WorkflowIdentity dari instans alur kerja yang bertahan. Dalam tutorial ini, kelas utilitas WorkflowVersionMap digunakan untuk memetakan WorkflowIdentity ke definisi alur kerja yang benar. Setelah definisi alur kerja diambil, WorkflowApplication dibuat, menggunakan definisi alur kerja yang benar.

    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. Setelah WorkflowApplication dibuat, konfigurasikan penyimpanan instans, penangan siklus hidup alur kerja, dan ekstensi dengan memanggil ConfigureWorkflowApplication. Langkah-langkah ini harus dilakukan setiap kali WorkflowApplication baru dibuat, dan harus dilakukan sebelum instans alur kerja dimuat ke dalam WorkflowApplication. Setelah dimuat, alur kerja dilanjutkan dengan tebakan pengguna.

    ' 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. Terakhir, kosongkan kotak teks tebakan dan siapkan formulir untuk menerima tebakan lain.

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

    Contoh berikut adalah penangan EnterGuess_Click yang telah selesai.

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

Untuk menghentikan alur kerja

  1. Tambahkan penangan Click untuk QuitGame. Untuk menambahkan penangan, alihkan ke Tampilan Desain untuk formulir, dan klik dua kali QuitGame. Setiap kali pengguna mengeklik tombol ini, alur kerja yang dipilih saat ini dihentikan.

    Private Sub QuitGame_Click(sender As Object, e As EventArgs) Handles QuitGame.Click
    
    End Sub
    
    private void QuitGame_Click(object sender, EventArgs e)
    {
    
    }
    
  2. Tambahkan kode berikut ke penangan QuitGame_Click. Kode ini pertama-tama memeriksa untuk memastikan bahwa alur kerja dipilih dalam daftar alur kerja. Kemudian memuat instans yang bertahan ke dalam WorkflowApplicationInstance, menggunakan DefinitionIdentity untuk menentukan definisi alur kerja yang benar, dan kemudian menginisialisasi WorkflowApplication. Selanjutnya ekstensi dan penangan siklus hidup alur kerja dikonfigurasi dengan panggilan ke ConfigureWorkflowApplication. Setelah WorkflowApplication dikonfigurasi, kode dimuat, dan kemudian Terminate dipanggil.

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

Untuk membangun dan menjalankan aplikasi

  1. Klik dua kali Program.cs (atau Module1.vb) di Penjelajah Solusi untuk menampilkan kode.

  2. Tambahkan pernyataan using (atau Imports) berikut di bagian atas file dengan pernyataan using (atau Imports) lainnya.

    Imports System.Windows.Forms
    
    using System.Windows.Forms;
    
  3. Hapus atau komentari kode hosting alur kerja yang ada dari Cara: Jalankan Alur Kerja, dan ganti dengan kode berikut.

    Sub Main()
        Application.EnableVisualStyles()
        Application.Run(New WorkflowHostForm())
    End Sub
    
    static void Main(string[] args)
    {
        Application.EnableVisualStyles();
        Application.Run(new WorkflowHostForm());
    }
    
  4. Klik kanan NumberGuessWorkflowHost di Penjelajah Solusi dan pilih Properti. Di tab Aplikasi, tentukan Aplikasi Windows untuk Jenis output. Langkah ini bersifat opsional, tetapi jika tidak diikuti, jendela konsol ditampilkan di samping formulir.

  5. Tekan Ctrl+Shift+B untuk membuat aplikasi.

  6. Pastikan NumberGuessWorkflowHost diatur sebagai aplikasi startup, dan tekan Ctrl+F5 untuk memulai aplikasi.

  7. Pilih rentang permainan tebak-tebakan dan jenis alur kerja yang akan dimulai, lalu klik Game Baru. Masukkan tebakan di kotak Tebakan dan klik Buka untuk mengirimkan tebakan Anda. Perhatikan bahwa output dari aktivitas WriteLine ditampilkan pada formulir.

  8. Mulai beberapa alur kerja menggunakan jenis alur kerja dan rentang angka yang berbeda, masukkan beberapa tebakan, dan beralih di antara alur kerja dengan memilih dari daftar ID Instans Alur Kerja.

    Perhatikan bahwa saat Anda beralih ke alur kerja baru, tebakan dan progres alur kerja sebelumnya tidak ditampilkan di jendela status. Alasan status tidak tersedia karena tidak diambil dan disimpan di mana saja. Pada langkah tutorial berikutnya, Cara: Membuat Peserta Pelacakan Kustom, Anda membuat peserta pelacakan kustom yang menyimpan informasi ini.