Uzun süre çalışan bir iş akışı oluşturma ve çalıştırma
Windows Workflow Foundation'ın (WF) temel özelliklerinden biri, çalışma zamanının boş iş akışlarını bir veritabanına kalıcı hale getirebilmesi ve kaldırabilmesidir. Nasıl yapılır: İş Akışı Çalıştırma'daki adımlar, konsol uygulaması kullanarak iş akışı barındırmanın temellerini göstermiştir. İş akışlarını başlatma, iş akışı yaşam döngüsü işleyicileri ve yer işaretlerini devam ettiren örnekler gösterilmiştir. İş akışı kalıcılığını etkili bir şekilde göstermek için, birden çok iş akışı örneğini başlatmayı ve devam ettiren daha karmaşık bir iş akışı konağı gereklidir. Öğreticideki bu adım, birden çok iş akışı örneğini başlatmayı ve devam ettirmeyi, iş akışı kalıcılığını destekleyen bir Windows form konak uygulamasının nasıl oluşturulacağını gösterir ve sonraki öğretici adımlarında gösterilen izleme ve sürüm oluşturma gibi gelişmiş özellikler için bir temel sağlar.
Not
Bu öğretici adımı ve sonraki adımlar, Nasıl yapılır: İş Akışı Oluşturma bölümünden üç iş akışı türünü de kullanır.
Kalıcılık veritabanını oluşturmak için
SQL Server Management Studio'yu açın ve yerel sunucuya bağlanın, örneğin .\SQLEXPRESS. Yerel sunucuda Veritabanları düğümüne sağ tıklayın ve Yeni Veritabanı'nı seçin. Yeni veritabanına WF45GettingStartedTutorial adını verin, diğer tüm değerleri kabul edin ve Tamam'ı seçin.
Not
Veritabanını oluşturmadan önce yerel sunucuda Veritabanı Oluşturma iznine sahip olduğunuzdan emin olun.
Dosya menüsünden Aç, Dosya'yı seçin. Şu klasöre göz atın: C:\Windows\Microsoft.NET\Framework\v4.0.30319\sql\en
Aşağıdaki iki dosyayı seçin ve Aç'a tıklayın.
SqlWorkflowInstanceStoreLogic.sql
SqlWorkflowInstanceStoreSchema.sql
Pencere menüsünden SqlWorkflowInstanceStoreSchema.sql seçin. Kullanılabilir Veritabanları açılan listesinde WF45GettingStartedTutorial seçeneğinin belirlendiğinden emin olun ve Sorgu menüsünden Yürüt'e tıklayın.
Pencere menüsünden SqlWorkflowInstanceStoreLogic.sql seçin. Kullanılabilir Veritabanları açılan listesinde WF45GettingStartedTutorial seçeneğinin belirlendiğinden emin olun ve Sorgu menüsünden Yürüt'e tıklayın.
Uyarı
Önceki iki adımı doğru sırada gerçekleştirmek önemlidir. Sorgular düzgün yürütülmezse hatalar oluşur ve kalıcılık veritabanı doğru yapılandırılmaz.
DurableInstancing derlemelerine başvuru eklemek için
Çözüm Gezgini'da NumberGuessWorkflowHost'a sağ tıklayın ve Başvuru Ekle'yi seçin.
Başvuru Ekle listesinden Derlemeler'i seçin ve Derlemeleri Ara kutusuna yazın
DurableInstancing
. Bu, derlemeleri filtreler ve istenen başvuruların seçilmesini kolaylaştırır.Arama Sonuçları listesinde System.Activities.DurableInstancing ve System.Runtime.DurableInstancing'in yanındaki onay kutusunu işaretleyin ve Tamam'a tıklayın.
İş akışı ana bilgisayar formunu oluşturmak için
Çözüm Gezgini'da NumberGuessWorkflowHost'a sağ tıklayın ve Ekle, Yeni Öğe'yi seçin.
Yüklü şablonlar listesinde Windows Formu'nu seçin, Ad kutusuna yazın
WorkflowHostForm
ve Ekle'ye tıklayın.Formda aşağıdaki özellikleri yapılandırın.
Özellik Değer FormBorderStyle FixedSingle MaximizeBox False Size 400, 420 Forma belirtilen sırayla aşağıdaki denetimleri ekleyin ve özellikleri yönlendirildi olarak yapılandırın.
Control Özellik: Değer Düğme Ad: NewGame
Konum: 13, 13
Boyut: 75, 23
Metin: Yeni OyunEtiket Konum: 94, 18
Metin: 1 ile bir sayıyı tahmin etmeComboBox Ad: NumberRange
DropDownStyle: DropDownList
Öğeler: 10, 100, 1000
Konum: 228, 12
Boyut: 143, 21Etiket Konum: 13, 43
Metin: İş akışı türüComboBox Ad: WorkflowType
DropDownStyle: DropDownList
Öğeler: StateMachineNumberGuessWorkflow, FlowchartNumberGuessWorkflow, SequentialNumberGuessWorkflow
Konum: 94, 40
Boyut: 277, 21Etiket Ad: WorkflowVersion
Konum: 13, 362
Metin: İş akışı sürümüGroupBox Konum: 13, 67
Boyut: 358, 287
Metin: OyunNot
Aşağıdaki denetimleri eklerken, bunları GroupBox'a yerleştirin.
Control Özellik: Değer Etiket Konum: 7, 20
Metin: İş Akışı Örneği KimliğiComboBox Ad: InstanceId
DropDownStyle: DropDownList
Konum: 121, 17
Boyut: 227, 21Etiket Konum: 7, 47
Metin: TahminTextBox Ad: Tahmin
Konum: 50, 44
Boyut: 65, 20Düğme Ad: EnterGuess
Konum: 121, 42
Boyut: 75, 23
Metin: Tahmin GirinDüğme Ad: QuitGame
Konum: 274, 42
Boyut: 75, 23
Metin: ÇıkTextBox Ad: WorkflowStatus
Konum: 10, 73
Çok Satırlı: True
ReadOnly: True
ScrollBars: Dikey
Boyut: 338, 208Formun AcceptButton özelliğini EnterGuess olarak ayarlayın.
Aşağıdaki örnekte tamamlanmış form gösterilmektedir.
Formun özelliklerini ve yardımcı yöntemlerini eklemek için
Bu bölümdeki adımlar, form sınıfına, çalıştırma ve numaralandırma sayısı tahmin iş akışlarını desteklemek için formun kullanıcı arabirimini yapılandıran özellikler ve yardımcı yöntemler ekler.
Çözüm Gezgini'da WorkflowHostForm'a sağ tıklayın ve Kodu Görüntüle'yi seçin.
Dosyanın en üstüne aşağıdaki
using
(veyaImports
) deyimlerini diğerusing
(veyaImports
) deyimleriyle ekleyin.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;
WorkflowHostForm sınıfına aşağıdaki üye bildirimlerini ekleyin.
Önemli
Microsoft, kullanılabilir en güvenli kimlik doğrulama akışını kullanmanızı önerir. Azure SQL'e bağlanıyorsanız önerilen kimlik doğrulama yöntemi Azure kaynakları için Yönetilen Kimlikler'dir.
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;
Not
bağlantı dizesi farklıysa, veritabanınıza başvurmak için güncelleştirin
connectionString
.sınıfına
WorkflowFormHost
birWorkflowInstanceId
özellik ekleyin.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; } }
Birleşik
InstanceId
giriş kutusu kalıcı iş akışı örneği kimliklerinin listesini görüntüler veWorkflowInstanceId
özelliği seçili durumdaki iş akışını döndürür.Form
Load
olayı için bir işleyici ekleyin. İşleyiciyi eklemek için formun Tasarım Görünümü'ne geçin, Özellikler penceresinin üst kısmındaki Olaylar simgesine tıklayın ve Yükle'ye çift tıklayın.Private Sub WorkflowHostForm_Load(sender As Object, e As EventArgs) Handles Me.Load End Sub
private void WorkflowHostForm_Load(object sender, EventArgs e) { }
Aşağıdaki kodu
WorkflowHostForm_Load
içine ekleyin.' 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();
Form yüklendiğinde,
SqlWorkflowInstanceStore
yapılandırılır, aralık ve iş akışı türü birleşik giriş kutuları varsayılan değerlere ayarlanır ve kalıcı iş akışı örnekleri birleşik giriş kutusunaInstanceId
eklenir.için
InstanceId
birSelectedIndexChanged
işleyici ekleyin. İşleyiciyi eklemek için formun Tasarım Görünümü'ne geçin, birleşik giriş kutusunu seçinInstanceId
, Özellikler penceresinin üst kısmındaki Olaylar simgesine tıklayın ve SelectedIndexChanged öğesine çift tıklayın.Private Sub InstanceId_SelectedIndexChanged(sender As Object, e As EventArgs) Handles InstanceId.SelectedIndexChanged End Sub
private void InstanceId_SelectedIndexChanged(object sender, EventArgs e) { }
Aşağıdaki kodu
InstanceId_SelectedIndexChanged
içine ekleyin. Kullanıcı birleşik giriş kutusunu kullanarak bir iş akışı seçtiğinde bu işleyici durum penceresini güncelleştirir.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(); }
Form sınıfına aşağıdaki
ListPersistedWorkflows
yöntemi ekleyin.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
kalıcı iş akışı örnekleri için örnek depoyu sorgular ve örnek kimliklerini birleşik giriş kutusunacboInstanceId
ekler.Form sınıfına aşağıdaki
UpdateStatus
yöntemi ve ilgili temsilciyi ekleyin. Bu yöntem, formdaki durum penceresini çalışmakta olan iş akışının durumuyla güncelleştirir.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(); } }
Form sınıfına aşağıdaki
GameOver
yöntemi ve ilgili temsilciyi ekleyin. Bir iş akışı tamamlandığında, bu yöntem InstanceId birleşik giriş kutusundan tamamlanan iş akışının örnek kimliğini kaldırarak form kullanıcı arabirimini güncelleştirir.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; } }
Örnek depoyu, iş akışı yaşam döngüsü işleyicilerini ve uzantıları yapılandırmak için
Form sınıfına bir
ConfigureWorkflowApplication
yöntem ekleyin.Private Sub ConfigureWorkflowApplication(wfApp As WorkflowApplication) End Sub
private void ConfigureWorkflowApplication(WorkflowApplication wfApp) { }
Bu yöntem, öğesini
WorkflowApplication
yapılandırarak istenen uzantıları ekler ve iş akışı yaşam döngüsü olayları için işleyiciler ekler.içinde
ConfigureWorkflowApplication
için öğesiniSqlWorkflowInstanceStore
WorkflowApplication
belirtin.' Configure the persistence store. wfApp.InstanceStore = store
// Configure the persistence store. wfApp.InstanceStore = store;
Ardından bir
StringWriter
örnek oluşturun ve koleksiyonunaExtensions
WorkflowApplication
ekleyin. Uzantılara birStringWriter
eklendiğinde tümWriteLine
etkinlik çıkışını yakalar. İş akışı boşta olduğunda,WriteLine
çıkış öğesindenStringWriter
ayıklanabilir ve formda görüntülenebilir.' 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);
Olay için aşağıdaki işleyiciyi
Completed
ekleyin. bir iş akışı başarıyla tamamlandığında, sayının tahminine yönelik dönüş sayısı durum penceresinde görüntülenir. İş akışı sonlandırılırsa sonlandırmaya neden olan özel durum bilgileri görüntülenir. İşleyicininGameOver
sonunda, tamamlanan iş akışını iş akışı listesinden kaldıran yöntemi çağrılır.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(); };
Aşağıdaki
Aborted
veOnUnhandledException
işleyicilerini ekleyin. İşGameOver
akışı örneği durdurulduğunda sonlandırılmadığından ve örneği daha sonra sürdürmek mümkün olduğundan yöntemi işleyicidenAborted
çağrılmaz.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; };
Aşağıdaki
PersistableIdle
işleyiciyi ekleyin. Bu işleyici eklenen uzantıyıStringWriter
alır, etkinliklerdenWriteLine
çıkışı ayıklar ve durum penceresinde görüntüler.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; };
Sabit PersistableIdleAction listesi üç değere sahiptir: None, Persist, ve Unload. Persist iş akışının kalıcı olmasını sağlar, ancak iş akışının kaldırılmasına neden olmaz. Unload iş akışının kalıcı hale gelip kaldırılmasına neden olur.
Aşağıdaki örnek, tamamlanmış
ConfigureWorkflowApplication
yöntemdir.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; }; }
Birden çok iş akışı türünün başlatılmasını ve devam ettirilmesine olanak tanımak için
Bir iş akışı örneğini sürdürmek için konağın iş akışı tanımını sağlaması gerekir. Bu öğreticide üç iş akışı türü vardır ve sonraki öğretici adımları bu türlerin birden çok sürümünü tanıtır. WorkflowIdentity
bir konak uygulamasının tanımlayıcı bilgileri kalıcı bir iş akışı örneğiyle ilişkilendirmesi için bir yol sağlar. Bu bölümdeki adımlarda, kalıcı bir iş akışı örneğinden ilgili iş akışı tanımına iş akışı kimliğini eşlemeye yardımcı olacak bir yardımcı program sınıfının nasıl oluşturulacağı gösterilmektedir. Ve sürüm oluşturma hakkında WorkflowIdentity
daha fazla bilgi için bkz . WorkflowIdentity ve Versioning kullanma.
Çözüm Gezgini'da NumberGuessWorkflowHost'a sağ tıklayın ve Ekle, Sınıf'ı seçin. Ad kutusuna yazın
WorkflowVersionMap
ve Ekle'ye tıklayın.Dosyanın en üstüne aşağıdaki
using
veyaImports
deyimlerini diğerusing
veyaImports
deyimleriyle ekleyin.Imports System.Activities Imports NumberGuessWorkflowActivities
using System.Activities; using NumberGuessWorkflowActivities;
sınıf bildirimini
WorkflowVersionMap
aşağıdaki bildirimle değiştirin.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
bu öğreticideki üç iş akışı tanımıyla eşlenen üç iş akışı kimliği içerir ve iş akışları başlatıldığında ve sürdürülürken aşağıdaki bölümlerde kullanılır.
Yeni bir iş akışı başlatmak için
için
NewGame
birClick
işleyici ekleyin. İşleyiciyi eklemek için formun Tasarım Görünümü'ne geçin ve öğesine çift tıklayınNewGame
. İşleyiciNewGame_Click
eklenir ve görünüm formun kod görünümüne geçer. Kullanıcı bu düğmeye her tıkladığınızda yeni bir iş akışı başlatılır.Private Sub NewGame_Click(sender As Object, e As EventArgs) Handles NewGame.Click End Sub
private void NewGame_Click(object sender, EventArgs e) { }
Tıklama işleyicisine aşağıdaki kodu ekleyin. Bu kod, iş akışı için bağımsız değişken adıyla anahtarlanan giriş bağımsız değişkenlerinden oluşan bir sözlük oluşturur. Bu sözlük, aralık birleşik giriş kutusundan alınan rastgele oluşturulan sayının aralığını içeren bir girdiye sahiptir.
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));
Ardından, iş akışını başlatan aşağıdaki kodu ekleyin.
WorkflowIdentity
Seçilen iş akışı türüne karşılık gelen ve iş akışı tanımı yardımcı sınıfı kullanılarakWorkflowVersionMap
alınır. Ardından, giriş bağımsız değişkenlerinin iş akışı tanımı,WorkflowIdentity
ve sözlüğü kullanılarak yeniWorkflowApplication
bir örnek oluşturulur.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);
Ardından, iş akışını iş akışı listesine ekleyen ve formda iş akışının sürüm bilgilerini görüntüleyen aşağıdaki kodu ekleyin.
' 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;
Bu
WorkflowApplication
örnek için örnek depoyu, uzantıları ve iş akışı yaşam döngüsü işleyicilerini yapılandırmak için çağrısıConfigureWorkflowApplication
yapın.' Configure the instance store, extensions, and ' workflow lifecycle handlers. ConfigureWorkflowApplication(wfApp)
// Configure the instance store, extensions, and // workflow lifecycle handlers. ConfigureWorkflowApplication(wfApp);
Son olarak öğesini arayın
Run
.' Start the workflow. wfApp.Run()
// Start the workflow. wfApp.Run();
Aşağıdaki örnek tamamlanmış
NewGame_Click
işleyicidir.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(); }
bir iş akışını sürdürmek için
için
EnterGuess
birClick
işleyici ekleyin. İşleyiciyi eklemek için formun Tasarım Görünümü'ne geçin ve öğesine çift tıklayınEnterGuess
. Kullanıcı bu düğmeye her tıkladığınızda bir iş akışı sürdürülür.Private Sub EnterGuess_Click(sender As Object, e As EventArgs) Handles EnterGuess.Click End Sub
private void EnterGuess_Click(object sender, EventArgs e) { }
İş akışı listesinde bir iş akışının seçildiğinden ve kullanıcının tahmininin geçerli olduğundan emin olmak için aşağıdaki kodu ekleyin.
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; }
Ardından kalıcı iş akışı örneğinin değerini alın
WorkflowApplicationInstance
. AWorkflowApplicationInstance
, henüz bir iş akışı tanımıyla ilişkilendirilmemiş kalıcı bir iş akışı örneğini temsil eder.DefinitionIdentity
,WorkflowApplicationInstance
kalıcı iş akışı örneğinin öğesini içerirWorkflowIdentity
. Bu öğreticideWorkflowVersionMap
yardımcı program sınıfı, öğesini doğru iş akışı tanımıyla eşlemekWorkflowIdentity
için kullanılır. İş akışı tanımı alındıktan sonra, doğru iş akışı tanımı kullanılarak birWorkflowApplication
oluşturulur.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);
WorkflowApplication
oluşturulduktan sonra çağrısı yaparakConfigureWorkflowApplication
örnek depoyu, iş akışı yaşam döngüsü işleyicilerini ve uzantıları yapılandırın. Bu adımlar her yeniWorkflowApplication
oluşturulduğunda ve iş akışı örneği içineWorkflowApplication
yüklenmeden önce yapılmalıdır. İş akışı yüklendikten sonra kullanıcının tahminiyle sürdürülür.' 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);
Son olarak, tahmin metin kutusunu temizleyin ve formu başka bir tahmini kabul etmek için hazırlayın.
' Clear the Guess textbox. Guess.Clear() Guess.Focus()
// Clear the Guess textbox. Guess.Clear(); Guess.Focus();
Aşağıdaki örnek tamamlanmış
EnterGuess_Click
işleyicidir.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(); }
İş akışını sonlandırmak için
için
QuitGame
birClick
işleyici ekleyin. İşleyiciyi eklemek için formun Tasarım Görünümü'ne geçin ve öğesine çift tıklayınQuitGame
. Kullanıcı bu düğmeye her tıkladığınızda seçili olan iş akışı sonlandırılır.Private Sub QuitGame_Click(sender As Object, e As EventArgs) Handles QuitGame.Click End Sub
private void QuitGame_Click(object sender, EventArgs e) { }
İşleyiciye
QuitGame_Click
aşağıdaki kodu ekleyin. Bu kod önce iş akışı listesinde bir iş akışının seçildiğinden emin olmak için denetler. Ardından kalıcı örneği içineWorkflowApplicationInstance
yükler, doğru iş akışı tanımını belirlemek için öğesiniDefinitionIdentity
kullanır ve ardından öğesiniWorkflowApplication
başlatır. Ardından uzantılar ve iş akışı yaşam döngüsü işleyicileri çağrısıylaConfigureWorkflowApplication
yapılandırılır.WorkflowApplication
yapılandırıldıktan sonra yüklenir ve çağrılırTerminate
.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.");
Uygulamayı derlemek ve çalıştırmak için
Kodu görüntülemek için Çözüm Gezgini'da Program.cs (veya Module1.vb) çift tıklayın.
Dosyanın en üstüne aşağıdaki
using
(veyaImports
) deyimini diğerusing
(veyaImports
) deyimleriyle ekleyin.Imports System.Windows.Forms
using System.Windows.Forms;
Nasıl yapılır: İş Akışı Çalıştırma'dan mevcut iş akışı barındırma kodunu kaldırın veya açıklama satırı yapın ve aşağıdaki kodla değiştirin.
Sub Main() Application.EnableVisualStyles() Application.Run(New WorkflowHostForm()) End Sub
static void Main(string[] args) { Application.EnableVisualStyles(); Application.Run(new WorkflowHostForm()); }
Çözüm Gezgini'da NumberGuessWorkflowHost'a sağ tıklayın ve Özellikler'i seçin. Uygulama sekmesinde, Çıkış türü için Windows Uygulaması'nı belirtin. Bu adım isteğe bağlıdır, ancak izlenmiyorsa forma ek olarak konsol penceresi de görüntülenir.
Uygulamayı derlemek için Ctrl+Shift+B tuşlarına basın.
NumberGuessWorkflowHost'un başlangıç uygulaması olarak ayarlandığından emin olun ve uygulamayı başlatmak için Ctrl+F5 tuşlarına basın.
Tahmin oyunu ve başlatacak iş akışı türü için bir aralık seçin ve Yeni Oyun'a tıklayın. Tahmin kutusuna bir tahmin girin ve tahmininizi göndermek için Git'e tıklayın. Etkinliklerden elde edilen çıkışın
WriteLine
formda görüntülendiğini unutmayın.Farklı iş akışı türleri ve sayı aralıkları kullanarak birkaç iş akışı başlatın, bazı tahminler girin ve İş Akışı Örneği Kimliği listesinden seçim yaparak iş akışları arasında geçiş yapın.
Yeni bir iş akışına geçtiğinizde, iş akışının önceki tahminlerinin ve ilerleme durumunun durum penceresinde görüntülenmediğini unutmayın. Durumun kullanılabilir olmamasının nedeni, herhangi bir yerde yakalanmaması ve kaydedilmemesidir. Öğreticinin bir sonraki adımı olan Nasıl yapılır: Özel İzleme Katılımcısı Oluşturma bölümünde, bu bilgileri kaydeden özel bir izleme katılımcısı oluşturacaksınız.