方法: カスタム追跡参加要素を作成する
ワークフロー追跡により、ワークフロー実行の状態が視覚的に示されます。 ワークフロー ランタイムによって、ワークフローのライフサイクル イベント、アクティビティのライフサイクル イベント、ブックマークの再開、およびエラーについて説明する追跡レコードが出力されます。 これらの追跡レコードは、追跡参加要素によって使用されます。 Windows Workflow Foundation (WF) には、追跡レコードを Event Tracing for Windows (ETW) イベントとして書き込む標準の追跡参加要素が含まれています。 これで要件が満たされない場合は、カスタムの追跡参加要素を作成することもできます。 チュートリアルのこの手順では、WriteLine
アクティビティの出力をキャプチャするカスタム追跡参加要素と追跡プロファイルを作成して、ユーザーに表示できるようにする方法について説明します。
カスタム追跡参加要素を作成するには
ソリューション エクスプローラーで NumberGuessWorkflowHost を右クリックし、 [追加] をポイントして、 [クラス] をクリックします。
StatusTrackingParticipant
[名前]ボックスに「」と入力して、[追加] をクリックします。次の
using
(またはImports
) ステートメントを、他のusing
(またはImports
) ステートメントを含むファイルの先頭に追加します。Imports System.Activities.Tracking Imports System.IO
using System.Activities.Tracking; using System.IO;
StatusTrackingParticipant
クラスを変更して、TrackingParticipant
から継承されるようにします。Public Class StatusTrackingParticipant Inherits TrackingParticipant End Class
class StatusTrackingParticipant : TrackingParticipant { }
次の
Track
メソッド オーバーライドを追加します。 追跡レコードには、いくつかの種類があります。 ここでは、アクティビティ追跡レコードに含まれるWriteLine
アクティビティの出力に注目します。TrackingRecord
がActivityTrackingRecord
アクティビティのWriteLine
である場合は、ワークフローのText
に基づいた名前の付いたファイルにWriteLine
のInstanceId
が追加されます。 このチュートリアルでは、ファイルはホスト アプリケーションの現在のフォルダーに保存されます。Protected Overrides Sub Track(record As TrackingRecord, timeout As TimeSpan) Dim asr As ActivityStateRecord = TryCast(record, ActivityStateRecord) If Not asr Is Nothing Then If asr.State = ActivityStates.Executing And _ asr.Activity.TypeName = "System.Activities.Statements.WriteLine" Then 'Append the WriteLine output to the tracking 'file for this instance. Using writer As StreamWriter = File.AppendText(record.InstanceId.ToString()) writer.WriteLine(asr.Arguments("Text")) writer.Close() End Using End If End If End Sub
protected override void Track(TrackingRecord record, TimeSpan timeout) { ActivityStateRecord asr = record as ActivityStateRecord; if (asr != null) { if (asr.State == ActivityStates.Executing && asr.Activity.TypeName == "System.Activities.Statements.WriteLine") { // Append the WriteLine output to the tracking // file for this instance using (StreamWriter writer = File.AppendText(record.InstanceId.ToString())) { writer.WriteLine(asr.Arguments["Text"]); writer.Close(); } } } }
追跡プロファイルを指定しない場合は、既定の追跡プロファイルが使用されます。 既定の追跡プロファイルを使用する場合は、すべての
ActivityStates
に関する追跡レコードが出力されます。 ここでは、WriteLine
アクティビティのライフサイクル中に 1 回だけテキストをキャプチャする必要があるため、ActivityStates.Executing
状態からテキストを抽出するだけです。 「追跡プロファイルを作成して追跡参加要素を登録するには」では、WriteLine
ActivityStates.Executing
の追跡レコードのみが出力されるように指定する追跡プロファイルを作成します。
追跡プロファイルを作成して追跡参加要素を登録するには
ソリューション エクスプローラーで WorkflowHostForm を右クリックし、 [コードの表示] をクリックします。
次の
using
(またはImports
) ステートメントを、他のusing
(またはImports
) ステートメントを含むファイルの先頭に追加します。Imports System.Activities.Tracking
using System.Activities.Tracking;
ワークフロー拡張機能に
ConfigureWorkflowApplication
を追加するコードの直後で、ワークフロー ライフサイクル ハンドラーの前に、StringWriter
に次のコードを追加します。'Add the custom tracking participant with a tracking profile 'that only emits tracking records for WriteLine activities. Dim query As New ActivityStateQuery() query.ActivityName = "WriteLine" query.States.Add(ActivityStates.Executing) query.Arguments.Add("Text") Dim profile As New TrackingProfile() profile.Queries.Add(query) Dim stp As New StatusTrackingParticipant() stp.TrackingProfile = profile wfApp.Extensions.Add(stp)
// Add the custom tracking participant with a tracking profile // that only emits tracking records for WriteLine activities. StatusTrackingParticipant stp = new StatusTrackingParticipant { TrackingProfile = new TrackingProfile { Queries = { new ActivityStateQuery { ActivityName = "WriteLine", States = { ActivityStates.Executing }, Arguments = { "Text" } } } } }; wfApp.Extensions.Add(stp);
この追跡プロファイルでは、
WriteLine
状態のExecuting
アクティビティのアクティビティ状態レコードのみがカスタム追跡参加要素に出力されるように指定します。このコードを追加した後、
ConfigureWorkflowApplication
の先頭は次の例のようになります。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) 'Add the custom tracking participant with a tracking profile 'that only emits tracking records for WriteLine activities. Dim query As New ActivityStateQuery() query.ActivityName = "WriteLine" query.States.Add(ActivityStates.Executing) query.Arguments.Add("Text") Dim profile As New TrackingProfile() profile.Queries.Add(query) Dim stp As New StatusTrackingParticipant() stp.TrackingProfile = profile wfApp.Extensions.Add(stp) 'Workflow lifecycle handlers...
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. StringWriter sw = new StringWriter(); wfApp.Extensions.Add(sw); // Add the custom tracking participant with a tracking profile // that only emits tracking records for WriteLine activities. StatusTrackingParticipant stp = new StatusTrackingParticipant { TrackingProfile = new TrackingProfile { Queries = { new ActivityStateQuery { ActivityName = "WriteLine", States = { ActivityStates.Executing }, Arguments = { "Text" } } } } }; wfApp.Extensions.Add(stp); // Workflow lifecycle handlers...
追跡情報を表示するには
ソリューション エクスプローラーで WorkflowHostForm を右クリックし、 [コードの表示] をクリックします。
InstanceId_SelectedIndexChanged
ハンドラーで、ステータス ウィンドウをクリアするコードの直後に次のコードを追加します。'If there is tracking data for this workflow, display it 'in the status window. If File.Exists(WorkflowInstanceId.ToString()) Then Dim status As String = File.ReadAllText(WorkflowInstanceId.ToString()) UpdateStatus(status) End If
// If there is tracking data for this workflow, display it // in the status window. if (File.Exists(WorkflowInstanceId.ToString())) { string status = File.ReadAllText(WorkflowInstanceId.ToString()); UpdateStatus(status); }
ワークフローの一覧で新しいワークフローを選択すると、そのワークフローの追跡レコードがステータス ウィンドウに読み込まれて表示されます。 完成した
InstanceId_SelectedIndexChanged
ハンドラーは次のようになります。Private Sub InstanceId_SelectedIndexChanged(sender As Object, e As EventArgs) Handles InstanceId.SelectedIndexChanged If InstanceId.SelectedIndex = -1 Then Return End If 'Clear the status window. WorkflowStatus.Clear() 'If there is tracking data for this workflow, display it 'in the status window. If File.Exists(WorkflowInstanceId.ToString()) Then Dim status As String = File.ReadAllText(WorkflowInstanceId.ToString()) UpdateStatus(status) End If '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 End Sub
private void InstanceId_SelectedIndexChanged(object sender, EventArgs e) { if (InstanceId.SelectedIndex == -1) { return; } // Clear the status window. WorkflowStatus.Clear(); // If there is tracking data for this workflow, display it // in the status window. if (File.Exists(WorkflowInstanceId.ToString())) { string status = File.ReadAllText(WorkflowInstanceId.ToString()); UpdateStatus(status); } // 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(); } }
アプリケーションをビルドして実行するには
Ctrl キーと Shift キーを押しながら B キーを押してアプリケーションをビルドします。
Ctrl キーを押しながら F5 キーを押してアプリケーションを起動します。
推測ゲームの範囲と開始するワークフローの種類を選択し、 [新しいゲーム] をクリックします。 [推定] ボックスに推定値を入力し、 [ジャンプ] をクリックして推定値を送信します。 ワークフローの状態がステータス ウィンドウに表示されます。 この出力は、
WriteLine
アクティビティからキャプチャされます。 [ワークフローインスタンス Id] ボックスの一覧で別のワークフローを選択してそのワークフローに切り替えて、現在のワークフローの状態が削除されることを確認します。 以前のワークフローに戻して、次の例のように、状態が復元されることを確認します。注意
追跡が有効になる前に開始されたワークフローに切り替えた場合、状態は表示されません。 ただし、推定値を追加すると、この時点では追跡が有効になっているため、その状態が保存されます。
Please enter a number between 1 and 10 Your guess is too high. Please enter a number between 1 and 10
注意
この情報は、乱数の範囲を決定する場合に役立ちますが、これまでに作成された推定値に関する情報を含んでいません。 この情報は、次のステップ「方法: ワークフローの複数のバージョンを同時にホストする」に記載されています。
ワークフロー インスタンス ID を書き留め、ゲームを最後まで実行します。
エクスプローラーを開き、NumberGuessWorkflowHost\bin\debug フォルダー (プロジェクトの設定によっては bin\release) に移動します。 プロジェクトの実行可能ファイルに加え、GUID ファイル名が付いたファイルがあることに注意します。 前の手順で完了したワークフローのワークフロー インスタンス ID に対応するファイルを特定してメモ帳で開きます。 追跡情報は、次のような情報が含まれています。
Please enter a number between 1 and 10 Your guess is too high. Please enter a number between 1 and 10 Your guess is too high. Please enter a number between 1 and 10
この追跡データには、ユーザーの推定値だけでなく、ワークフローの最後の推定値に関する情報も含まれていません。 これは、追跡情報がワークフローからの
WriteLine
出力のみで構成されており、表示される最後のメッセージがワークフロー完了後にCompleted
ハンドラーから表示されるためです。 チュートリアルの次のステップ「方法: ワークフローの複数のバージョンを同時にホストする」では、ユーザーの推定値が表示されるように既存のWriteLine
アクティビティを変更し、最終結果を表示する新しいWriteLine
アクティビティを追加します。 これらの変更を統合した後、「方法: ワークフローの複数のバージョンを同時にホストする」で、ワークフローの複数のバージョンを同時にホストする方法について説明します。
.NET