Poznámka:
Přístup k této stránce vyžaduje autorizaci. Můžete se zkusit přihlásit nebo změnit adresáře.
Přístup k této stránce vyžaduje autorizaci. Můžete zkusit změnit adresáře.
Jednou z hlavních funkcí windows Workflow Foundation (WF) je schopnost modulu runtime zachovat a uvolnit nečinné pracovní postupy do databáze. Kroky v části Postupy: Spuštění pracovního postupu demonstrovalo základy hostování pracovních postupů pomocí konzolové aplikace. Příklady spouštění pracovních postupů, obslužných rutin životního cyklu pracovního postupu a obnovení záložek Aby bylo možné efektivně předvést trvalost pracovního postupu, je vyžadován složitější hostitel pracovního postupu, který podporuje spouštění a obnovování více instancí pracovního postupu. Tento krok v tomto kurzu ukazuje, jak vytvořit hostitelskou aplikaci formuláře Windows, která podporuje spouštění a obnovení více instancí pracovního postupu, trvalost pracovních postupů a poskytuje základ pro pokročilé funkce, jako je sledování a správa verzí, které jsou demonstrována v dalších krocích kurzu.
Poznámka:
Tento krok kurzu a následné kroky používají všechny tři typy pracovních postupů: Vytvoření pracovního postupu.
Vytvoření databáze trvalosti
Otevřete APLIKACI SQL Server Management Studio a připojte se k místnímu serveru, například .\SQLEXPRESS. Klikněte pravým tlačítkem myši na uzel Databáze na místním serveru a vyberte Nová databáze. Pojmenujte novou databázi WF45GettingStartedTutorial, přijměte všechny ostatní hodnoty a vyberte OK.
Poznámka:
Před vytvořením databáze se ujistěte, že máte na místním serveru oprávnění k vytvoření databáze.
V nabídce Soubor zvolte Otevřít, Soubor. Přejděte do následující složky: C:\Windows\Microsoft.NET\Framework\v4.0.30319\sql\en
Vyberte následující dva soubory a klikněte na Otevřít.
SqlWorkflowInstanceStoreLogic.sql
SqlWorkflowInstanceStoreSchema.sql
V nabídce Okno zvolte SqlWorkflowInstanceStoreSchema.sql. Ujistěte se, že je v rozevíracím seznamu Dostupné databáze vybraná možnost WF45GettingStartedTutorial a v nabídce Dotaz zvolte Spustit.
V nabídce Okno zvolte SqlWorkflowInstanceStoreLogic.sql. Ujistěte se, že je v rozevíracím seznamu Dostupné databáze vybraná možnost WF45GettingStartedTutorial a v nabídce Dotaz zvolte Spustit.
Upozorňující
Je důležité provést předchozí dva kroky ve správném pořadí. Pokud jsou dotazy prováděny mimo pořadí, dojde k chybám a databáze trvalosti není správně nakonfigurovaná.
Přidání odkazu na sestavení DurableInstancing
Klikněte pravým tlačítkem na NumberGuessWorkflowHost v Průzkumník řešení a vyberte Přidat odkaz.
V seznamu Přidat odkaz vyberte sestavení a zadejte
DurableInstancingdo pole Hledat sestavení. Tím se vyfiltrují sestavení a usnadní se výběr požadovaných odkazů.Zaškrtněte políčko vedle položky System.Activities.DurableInstancing a System.Runtime.DurableInstancing ze seznamu výsledků hledání a klepněte na tlačítko OK.
Vytvoření formuláře hostitele pracovního postupu
Klikněte pravým tlačítkem na NumberGuessWorkflowHost v Průzkumník řešení a zvolte Přidat, Nová položka.
V seznamu Nainstalované šablony zvolte Formulář Systému Windows, zadejte
WorkflowHostFormdo pole Název a klepněte na tlačítko Přidat.Ve formuláři nakonfigurujte následující vlastnosti.
Vlastnost Hodnota FormBorderStyle Pevná single MaximalizovatBox False Velikost 400, 420 Do formuláře v uvedeném pořadí přidejte následující ovládací prvky a nakonfigurujte vlastnosti podle pokynů.
Ovládací prvek Vlastnost: Hodnota Tlačítko Název: NewGame
Umístění: 13, 13
Velikost: 75, 23
Text: Nová hraPopisek Umístění: 94, 18
Text: Odhad čísla od 1 doComboBox Název: NumberRange
DropDownStyle: DropDownList
Položky: 10, 100, 1000
Umístění: 228, 12
Velikost: 143, 21Popisek Umístění: 13, 43
Text: Typ pracovního postupuComboBox Název: WorkflowType
DropDownStyle: DropDownList
Položky: StateMachineNumberGuessWorkflow, FlowchartNumberGuessWorkflow, SequentialNumberGuessWorkflow
Umístění: 94, 40
Velikost: 277, 21Popisek Název: WorkflowVersion
Umístění: 13, 362
Text: Verze pracovního postupuGroupBox Umístění: 13, 67
Velikost: 358, 287
Text: HraPoznámka:
Při přidávání následujících ovládacích prvků je vložte do GroupBoxu.
Ovládací prvek Vlastnost: Hodnota Popisek Umístění: 7, 20
Text: ID instance pracovního postupuComboBox Název: InstanceId
DropDownStyle: DropDownList
Umístění: 121, 17
Velikost: 227, 21Popisek Umístění: 7, 47
Text: OdhadTextBox Název: Odhad
Umístění: 50, 44
Velikost: 65, 20Tlačítko Název: EnterGuess
Umístění: 121, 42
Velikost: 75, 23
Text: Zadejte odhad.Tlačítko Název: QuitGame
Umístění: 274, 42
Velikost: 75, 23
Text: UkončitTextBox Název: WorkflowStatus
Umístění: 10, 73
Víceřádkový: True
ReadOnly: True
Posuvníky: Svisle
Velikost: 338, 208Nastavte AcceptButton vlastnost formuláře EnterGuess.
Následující příklad znázorňuje dokončený formulář.

Přidání vlastností a pomocných metod formuláře
Kroky v této části přidávají vlastnosti a pomocné metody do třídy formuláře, které konfigurují uživatelské rozhraní formuláře tak, aby podporovaly spouštění a obnovení pracovních postupů odhadu čísel.
Pravým tlačítkem myši klikněte na WorkflowHostForm v Průzkumník řešení a zvolte Zobrazit kód.
Do horní části souboru přidejte následující
usingpříkazy (neboImports) s jinýmiusingpříkazy (neboImports).Imports System.Activities Imports System.Activities.DurableInstancing Imports System.Data.SqlClient Imports System.IO Imports System.Windows.Formsusing System.Activities; using System.Activities.DurableInstancing; using System.Data.SqlClient; using System.IO; using System.Windows.Forms;Do třídy WorkflowHostForm přidejte následující deklarace členů.
Důležité
Microsoft doporučuje používat nejbezpečnější dostupný tok ověřování. Pokud se připojujete k Azure SQL, spravované identity pro prostředky Azure se doporučují metodou ověřování.
Const connectionString = "Server=.\SQLEXPRESS;Initial Catalog=WF45GettingStartedTutorial;Integrated Security=SSPI" Dim store As SqlWorkflowInstanceStore Dim workflowStarting As Booleanconst string connectionString = "Server=.\\SQLEXPRESS;Initial Catalog=WF45GettingStartedTutorial;Integrated Security=SSPI"; SqlWorkflowInstanceStore store; bool workflowStarting;Poznámka:
Pokud se vaše připojovací řetězec liší, aktualizujte
connectionStringdatabázi.WorkflowInstanceIdPřidejte do třídy vlastnostWorkflowFormHost.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 Propertypublic Guid WorkflowInstanceId { get { return InstanceId.SelectedIndex == -1 ? Guid.Empty : (Guid)InstanceId.SelectedItem; } }Pole
InstanceIdse seznamem zobrazí seznam id trvalých instancí pracovního postupu aWorkflowInstanceIdvlastnost vrátí aktuálně vybraný pracovní postup.Přidejte obslužnou rutinu události formuláře
Load. Pokud chcete přidat obslužnou rutinu, přepněte do návrhového zobrazení formuláře, klikněte v horní části okna Vlastnosti na ikonu Události a poklikejte na Načíst.Private Sub WorkflowHostForm_Load(sender As Object, e As EventArgs) Handles Me.Load End Subprivate void WorkflowHostForm_Load(object sender, EventArgs e) { }Přidejte následující kód do
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();Když se formulář načte, nakonfiguruje se
SqlWorkflowInstanceStorepole se seznamem rozsahu a typu pracovního postupu na výchozí hodnoty a trvalé instance pracovního postupu se přidají do pole se seznamemInstanceId.Přidání obslužné rutiny
SelectedIndexChangedproInstanceId. Chcete-li přidat obslužnou rutinu, přepněte do návrhového zobrazení formuláře, vyberteInstanceIdpole se seznamem, klikněte na ikonu Události v horní části okna Vlastnosti a poklikejte na SelectedIndexChanged.Private Sub InstanceId_SelectedIndexChanged(sender As Object, e As EventArgs) Handles InstanceId.SelectedIndexChanged End Subprivate void InstanceId_SelectedIndexChanged(object sender, EventArgs e) { }Přidejte následující kód do
InstanceId_SelectedIndexChanged. Kdykoli uživatel vybere pracovní postup pomocí pole se seznamem, tato obslužná rutina aktualizuje stavové okno.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 Ifif (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(); }Do třídy formuláře přidejte následující
ListPersistedWorkflowsmetodu.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 Subusing (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); } } }ListPersistedWorkflowsdotazuje úložiště instancí pro trvalé instance pracovního postupu a přidá ID instance do pole se seznamemcboInstanceId.Přidejte následující
UpdateStatusmetodu a odpovídající delegáta do třídy formuláře. Tato metoda aktualizuje stavové okno ve formuláři se stavem aktuálně spuštěného pracovního postupu.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 Subprivate 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(); } }Přidejte následující
GameOvermetodu a odpovídající delegáta do třídy formuláře. Po dokončení pracovního postupu tato metoda aktualizuje uživatelské rozhraní formuláře odebráním ID instance dokončeného pracovního postupu ze pole se seznamem 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 Subprivate 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; } }
Konfigurace úložiště instancí, obslužných rutin životního cyklu pracovního postupu a rozšíření
Přidejte metodu
ConfigureWorkflowApplicationdo třídy formuláře.Private Sub ConfigureWorkflowApplication(wfApp As WorkflowApplication) End Subprivate void ConfigureWorkflowApplication(WorkflowApplication wfApp) { }Tato metoda nakonfiguruje
WorkflowApplication, přidá požadovaná rozšíření a přidá obslužné rutiny pro události životního cyklu pracovního postupu.Do
ConfigureWorkflowApplicationpoleSqlWorkflowInstanceStorezadejte hodnotu .WorkflowApplication' Configure the persistence store. wfApp.InstanceStore = store// Configure the persistence store. wfApp.InstanceStore = store;Dále vytvořte
StringWriterinstanci a přidejte ji doExtensionskolekce objektuWorkflowApplication.StringWriterKdyž se přidá do rozšíření, zachytí se veškerýWriteLinevýstup aktivity. Když se pracovní postup změní na nečinný,WriteLinemůžete výstup extrahovat zStringWriterformuláře a zobrazit ho.' 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);Přidejte následující obslužnou rutinu
Completedudálosti. Po úspěšném dokončení pracovního postupu se v okně stavu zobrazí počet provedených kroků, aby bylo odhadnuto číslo. Pokud pracovní postup skončí, zobrazí se informace o výjimce, které způsobily ukončení. Na konci obslužné rutinyGameOverje volána metoda, která odebere dokončený pracovní postup ze seznamu pracovních postupů.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 SubwfApp.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(); };Přidejte následující
AbortedaOnUnhandledExceptionobslužné rutiny. MetodaGameOvernení volána zAbortedobslužné rutiny, protože když je instance pracovního postupu přerušena, neukončí a je možné obnovit instanci později.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 FunctionwfApp.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; };Přidejte následující
PersistableIdleobslužnou rutinu. Tato obslužná rutinaStringWriternačte přidané rozšíření, extrahuje výstup zWriteLineaktivit a zobrazí ho v okně stavu.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 FunctionwfApp.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; };Výčet PersistableIdleAction má tři hodnoty: None, Persista Unload. Persist způsobí zachování pracovního postupu, ale nezpůsobí uvolnění pracovního postupu. Unload způsobí trvalé a uvolněné pracovní postup.
Následující příklad je dokončená
ConfigureWorkflowApplicationmetoda.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 Subprivate 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; }; }
Povolení spuštění a obnovení více typů pracovních postupů
Aby bylo možné obnovit instanci pracovního postupu, musí hostitel zadat definici pracovního postupu. V tomto kurzu existují tři typy pracovních postupů a následné kroky kurzu představují více verzí těchto typů. WorkflowIdentity poskytuje způsob, jak hostitelská aplikace přidružit identifikaci informací k trvalé instanci pracovního postupu. Kroky v této části ukazují, jak vytvořit třídu nástrojů, která vám pomůže s mapováním identity pracovního postupu z trvalé instance pracovního postupu na odpovídající definici pracovního postupu. Další informace o WorkflowIdentity správě verzí a správu verzí naleznete v tématu Použití WorkflowIdentity a správy verzí.
Klikněte pravým tlačítkem na NumberGuessWorkflowHost v Průzkumník řešení a zvolte Přidat, Třída. Zadejte
WorkflowVersionMapdo pole Název a klikněte na Přidat.Do horní části souboru přidejte následující
usingpříkazy neboImportspříkazy s jinýmiusingpříkazy neboImportspříkazy.Imports System.Activities Imports NumberGuessWorkflowActivitiesusing System.Activities; using NumberGuessWorkflowActivities;WorkflowVersionMapNahraďte deklaraci třídy následující deklarací.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 Modulepublic 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(); } }WorkflowVersionMapobsahuje tři identity pracovního postupu, které se mapují na tři definice pracovního postupu z tohoto kurzu, a používá se v následujících částech při spuštění a obnovení pracovních postupů.
Zahájení nového pracovního postupu
Přidání obslužné rutiny
ClickproNewGame. Chcete-li přidat obslužnou rutinu, přepněte do návrhového zobrazení formuláře a poklikejte naNewGametlačítko . Přidá se obslužnáNewGame_Clickrutina a zobrazení se přepne do zobrazení kódu formuláře. Pokaždé, když uživatel klikne na toto tlačítko, spustí se nový pracovní postup.Private Sub NewGame_Click(sender As Object, e As EventArgs) Handles NewGame.Click End Subprivate void NewGame_Click(object sender, EventArgs e) { }Do obslužné rutiny kliknutí přidejte následující kód. Tento kód vytvoří slovník vstupníchargumentch Tento slovník obsahuje jednu položku, která obsahuje oblast náhodně vygenerovaného čísla načteného z pole se seznamem rozsahu.
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));Dále přidejte následující kód, který spouští pracovní postup. Definice
WorkflowIdentitypracovního postupu odpovídající vybranému typu pracovního postupu se načte pomocíWorkflowVersionMappomocné třídy. Dále se vytvoří nováWorkflowApplicationinstance pomocí definiceWorkflowIdentitypracovního postupu a slovníku vstupních argumentů.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);Dále přidejte následující kód, který přidá pracovní postup do seznamu pracovních postupů a zobrazí informace o verzi pracovního postupu ve formuláři.
' 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;Volání
ConfigureWorkflowApplicationkonfigurace úložiště instancí, rozšíření a obslužných rutin životního cyklu pracovního postupu pro tutoWorkflowApplicationinstanci' Configure the instance store, extensions, and ' workflow lifecycle handlers. ConfigureWorkflowApplication(wfApp)// Configure the instance store, extensions, and // workflow lifecycle handlers. ConfigureWorkflowApplication(wfApp);Nakonec zavolejte
Run.' Start the workflow. wfApp.Run()// Start the workflow. wfApp.Run();Následující příklad je dokončená obslužná
NewGame_Clickrutina.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 Subprivate 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(); }
Obnovení pracovního postupu
Přidání obslužné rutiny
ClickproEnterGuess. Chcete-li přidat obslužnou rutinu, přepněte do návrhového zobrazení formuláře a poklikejte naEnterGuesstlačítko . Kdykoli uživatel klikne na toto tlačítko, pracovní postup se obnoví.Private Sub EnterGuess_Click(sender As Object, e As EventArgs) Handles EnterGuess.Click End Subprivate void EnterGuess_Click(object sender, EventArgs e) { }Přidejte následující kód, který zajistí, že je v seznamu pracovních postupů vybraný pracovní postup a zda je odhad uživatele platný.
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 Ifif (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; }Dále načtěte
WorkflowApplicationInstancetrvalou instanci pracovního postupu. AWorkflowApplicationInstancepředstavuje trvalou instanci pracovního postupu, která ještě nebyla přidružena k definici pracovního postupu. TheDefinitionIdentityof theWorkflowApplicationInstancecontains theWorkflowIdentitypersisted workflow instance. V tomto kurzuWorkflowVersionMapse třída nástroje používá k mapováníWorkflowIdentityna správnou definici pracovního postupu. Jakmile se definice pracovního postupu načte, vytvoří seWorkflowApplicationpomocí správné definice pracovního postupu.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);WorkflowApplicationPo vytvoření nakonfigurujte úložiště instancí, obslužné rutiny životního cyklu pracovního postupu a rozšíření volánímConfigureWorkflowApplication. Tyto kroky musí být provedeny při každém vytvoření novéhoWorkflowApplicationa musí být provedeny před načtením instance pracovního postupu doWorkflowApplication. Po načtení pracovního postupu se obnoví odhad uživatele.' 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);Nakonec vymažte textové pole pro odhad a připravte formulář na přijetí dalšího odhadu.
' Clear the Guess textbox. Guess.Clear() Guess.Focus()// Clear the Guess textbox. Guess.Clear(); Guess.Focus();Následující příklad je dokončená obslužná
EnterGuess_Clickrutina.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 Subprivate 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(); }
Ukončení pracovního postupu
Přidání obslužné rutiny
ClickproQuitGame. Chcete-li přidat obslužnou rutinu, přepněte do návrhového zobrazení formuláře a poklikejte naQuitGametlačítko . Kdykoli uživatel klikne na toto tlačítko, ukončí se aktuálně vybraný pracovní postup.Private Sub QuitGame_Click(sender As Object, e As EventArgs) Handles QuitGame.Click End Subprivate void QuitGame_Click(object sender, EventArgs e) { }Do obslužné rutiny
QuitGame_Clickpřidejte následující kód. Tento kód nejprve zkontroluje, jestli je v seznamu pracovních postupů vybraný pracovní postup. Pak načte trvalou instanci do ,WorkflowApplicationInstancepoužijeDefinitionIdentityk určení správné definice pracovního postupu a pak inicializujeWorkflowApplication. Dále jsou obslužné rutiny životního cyklu rozšíření a pracovního postupu nakonfigurovány s volánímConfigureWorkflowApplication. Po nakonfigurováníWorkflowApplicationse načte a pakTerminatese zavolá.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.");
Sestavení a spuštění aplikace
Poklikáním na Program.cs (nebo Module1.vb) v Průzkumník řešení zobrazíte kód.
Do horní části souboru přidejte následující
usingpříkaz (neboImports) s jinýmiusingpříkazy (neboImports).Imports System.Windows.Formsusing System.Windows.Forms;Odeberte nebo zakomentujte existující kód hostování pracovního postupu z postupu: Spusťte pracovní postup a nahraďte ho následujícím kódem.
Sub Main() Application.EnableVisualStyles() Application.Run(New WorkflowHostForm()) End Substatic void Main(string[] args) { Application.EnableVisualStyles(); Application.Run(new WorkflowHostForm()); }Klikněte pravým tlačítkem na NumberGuessWorkflowHost v Průzkumník řešení a zvolte Vlastnosti. Na kartě Aplikace zadejte aplikaci systému Windows pro typ výstupu. Tento krok je nepovinný, ale pokud není následovaný oknem konzoly, zobrazí se vedle formuláře.
Stisknutím kombinace kláves Ctrl+Shift+B sestavte aplikaci.
Ujistěte se, že je parametr NumberGuessWorkflowHost nastavený jako spouštěcí aplikace, a stisknutím kombinace kláves Ctrl+F5 spusťte aplikaci.
Vyberte oblast pro hádanou hru a typ pracovního postupu, který chcete spustit, a klikněte na Tlačítko Nová hra. Do pole Hádejte zadejte odhad a kliknutím na Přejít odešlete svůj odhad. Všimněte si, že výstup z
WriteLineaktivit se zobrazí ve formuláři.Spusťte několik pracovních postupů pomocí různých typů pracovních postupů a rozsahů čísel, zadejte určité odhady a přepněte mezi pracovními postupy výběrem ze seznamu ID instance pracovního postupu.
Všimněte si, že když přepnete na nový pracovní postup, předchozí odhady a průběh pracovního postupu se v okně stavu nezobrazí. Důvodem, proč stav není dostupný, je to, že se nezachytí a neuloží kamkoliv. V dalším kroku kurzu Postupy : Vytvoření vlastního účastníka sledování vytvoříte vlastního účastníka sledování, který uloží tyto informace.