Procedimiento para crear un participante de seguimiento personalizado
El seguimiento de flujo de trabajo proporciona visibilidad del estado de la ejecución del flujo de trabajo. El runtime de flujo de trabajo emite registros de seguimiento que describen los eventos de ciclo de vida de flujo de trabajo, los eventos de ciclo de vida de actividad, los errores y la reanudación de marcadores. Los participantes de seguimiento usan estos registros de seguimiento. Windows Workflow Foundation (WF) incluye un participante de seguimiento estándar que escribe los registros de seguimiento como eventos de Seguimiento de eventos para Windows (ETW). Si eso no cumple sus requisitos, también puede escribir un participante de seguimiento personalizado. Este paso del tutorial describe cómo crear un participante y un perfil de seguimiento personalizados que capturen la salida de las actividades WriteLine
para poder mostrarla al usuario.
Para crear el participante de seguimiento personalizado
Haga clic con el botón derecho en NumberGuessWorkflowHost en el Explorador de soluciones y elija Agregar, Clase. Escriba
StatusTrackingParticipant
en el cuadro Nombre y haga clic en Agregar.Agregue las siguientes instrucciones
using
(oImports
) al principio del archivo con las demás instruccionesusing
(oImports
).Imports System.Activities.Tracking Imports System.IO
using System.Activities.Tracking; using System.IO;
Modifique la clase
StatusTrackingParticipant
para que herede deTrackingParticipant
.Public Class StatusTrackingParticipant Inherits TrackingParticipant End Class
class StatusTrackingParticipant : TrackingParticipant { }
Agregue el siguiente remplazo de método
Track
. Hay varios tipos distintos de registros de seguimiento. Estamos interesados en el resultado de las actividades deWriteLine
, contenidas en registros de seguimiento de actividad. SiTrackingRecord
es unActivityTrackingRecord
para una actividadWriteLine
,Text
deWriteLine
se anexa a un archivo con una nombre segúnInstanceId
del flujo de trabajo. En este tutorial, el archivo se guarda en la carpeta actual de la aplicación de host.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(); } } } }
Cuando no se especifica ningún perfil de seguimiento, se usa el perfil de seguimiento predeterminado. Cuando se usa el perfil de seguimiento predeterminado, los registros de seguimiento se emiten para todos
ActivityStates
. Dado que solo debemos capturar el texto una vez durante el ciclo de vida de la actividadWriteLine
, solo extraemos el texto del estadoActivityStates.Executing
. En Para crear el perfil de seguimiento y registrar el participante de seguimiento, se crea un perfil de seguimiento que especifica que solo se emiten los registros de seguimiento deWriteLine
ActivityStates.Executing
.
Para crear el perfil de seguimiento y registrar el participante de seguimiento
Haga clic con el botón derecho en WorkflowHostForm en Explorador de soluciones y elija Ver código.
Agregue las siguientes instrucciones
using
(oImports
) al principio del archivo con las demás instruccionesusing
(oImports
).Imports System.Activities.Tracking
using System.Activities.Tracking;
Agregue el código siguiente a
ConfigureWorkflowApplication
justo después del código que agregaStringWriter
a las extensiones de flujo de trabajo y justo antes de los controladores de ciclo de vida de flujo de trabajo.'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);
Este perfil de seguimiento especifica que solo los registros de estado de actividad para actividades
WriteLine
en el estado deExecuting
se emiten al participante de seguimiento personalizado.Después de agregar el código, el inicio de
ConfigureWorkflowApplication
será como el ejemplo siguiente.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...
Para mostrar la información de seguimiento
Haga clic con el botón derecho en WorkflowHostForm en Explorador de soluciones y elija Ver código.
En el controlador de
InstanceId_SelectedIndexChanged
, agregue el código siguiente inmediatamente después del código que borra la ventana de estado.'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); }
Cuando se selecciona un nuevo flujo de trabajo en la lista de flujos de trabajo, los registros de seguimiento para ese flujo de trabajo se cargan y se muestran en la ventana de estado. El siguiente ejemplo es el controlador
InstanceId_SelectedIndexChanged
completado.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(); } }
Para generar y ejecutar la aplicación
Presione Ctrl+Mayús+B para compilar la aplicación.
Presione Ctrl + F5 para iniciar la aplicación.
Seleccione un intervalo para el juego de adivinar un numero y el tipo de flujo de trabajo que se va a iniciar, y haga clic en New Game (Nuevo juego). Escriba un intento en el cuadro de Guess (Adivinar) y haga clic en Go (Ir) para enviarlo. Observe que el estado del flujo de trabajo se muestra en la ventana de estado. Este resultado se captura de las actividades de
WriteLine
. Cambie a un flujo de trabajo diferente mediante la selección de uno en el cuadro combinado Identificador de instancia de flujo de trabajo y observe que el estado del flujo de trabajo actual se ha quitado. Cambie de nuevo al flujo de trabajo anterior y observe que se restablece el estado, similar al siguiente ejemplo.Nota
Si cambia a un flujo de trabajo que se había iniciado antes de que se habilitara el seguimiento, no se mostrará ningún estado. Sin embargo, si hace intentos adicionales, el estado se guarda porque ahora se ha habilitado el seguimiento.
Please enter a number between 1 and 10 Your guess is too high. Please enter a number between 1 and 10
Nota
Esta información es útil para determinar el intervalo del número aleatorio, pero no contiene información sobre qué intentos se han hecho anteriormente. Esta información se encuentra en el paso siguiente: Cómo hospedar varias versiones de un flujo de trabajo en paralelo.
Anote el identificador de instancias de flujo de trabajo, y juegue hasta completar el juego.
Abra el Explorador de Windows y vaya a la carpeta NumberGuessWorkflowHost\bin\debug (o bin\release según la configuración del proyecto). Observe que además de los archivos ejecutables del proyecto hay archivos con nombres de archivo guid. Identifique cuál corresponde al identificador de instancia del flujo de trabajo completado en el paso anterior y ábralo en el Bloc de notas. La información de seguimiento incluye información similar a la siguiente.
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
Además de no contener los intentos del usuario, este dato de seguimiento no contiene información sobre el último intento del flujo de trabajo. Esto se debe a que la información de seguimiento solo consta del resultado de
WriteLine
del flujo de trabajo, y el mensaje final que se muestra se hace así desde el controlador deCompleted
una vez el flujo de trabajo se ha completado. En el siguiente paso del tutorial Cómo hospedar varias versiones de un flujo de trabajo en paralelo, las actividadesWriteLine
existentes se modifican para mostrar los intentos del usuario y se agrega una actividadWriteLine
adicional que muestra el resultado final. Una vez integrados estos cambios, en Cómo hospedar varias versiones de un flujo de trabajo en paralelo se muestra cómo hospedar varias versiones de un flujo de trabajo al mismo tiempo.