Procedimiento para hospedar varias versiones de un flujo de trabajo en paralelo
WorkflowIdentity
proporciona una manera para que los desarrolladores de aplicaciones de flujo de trabajo asocien un nombre y una versión con una definición de flujo de trabajo, y para que esta información se asocie a una instancia de flujo de trabajo persistente. Los desarrolladores de aplicaciones de flujo de trabajo pueden usar esta información de identidad para habilitar escenarios como la ejecución en paralelo de varias versiones de una definición de flujo de trabajo; además esta información proporciona la piedra angular para otras funcionalidades como la actualización dinámica. Este paso del tutorial demuestra cómo usar WorkflowIdentity
para hospedar varias versiones de un flujo de trabajo simultáneamente.
En este tema
En este paso del tutorial, las actividades de WriteLine
en el flujo de trabajo se modifican para proporcionar información adicional y se agrega una nueva actividad WriteLine
. Una copia del ensamblado original de flujo de trabajo queda almacenada y la aplicación de host se actualiza de tal modo que puede ejecutar tanto el flujo de trabajo original como el actualizado al mismo tiempo.
Para realizar una copia del proyecto NumberGuessWorkflowActivities
Para actualizar WorkflowVersionMap a fin de incluir las versiones de flujo de trabajo anteriores
Nota
Antes de seguir los pasos de este tema, ejecute la aplicación, inicie varios flujos de trabajo de cada tipo y realice uno o dos intentos con cada uno. Estos flujos de trabajo persistentes se utilizan en este paso y en el siguiente, Procedimiento para actualizar la definición de una instancia de flujo de trabajo en ejecución.
Para realizar una copia del proyecto NumberGuessWorkflowActivities
Abra la solución WF45GettingStartedTutorial en Visual Studio 2012 si no está abierta.
Presione CTRL+MAYÚS+B para compilar la solución.
Cierre la solución WF45GettingStartedTutorial.
Abra el Explorador de Windows y navegue hasta la carpeta donde se encuentran el archivo de solución del tutorial y las carpetas de proyecto.
Cree una carpeta denominada PreviousVersions en la misma carpeta que NumberGuessWorkflowHost y NumberGuessWorkflowActivities. Esta carpeta se usa para guardar los ensamblados que contienen las distintas versiones de los flujos de trabajo usados en los pasos de tutorial posteriores.
Navegue a la carpeta NumberGuessWorkflowActivities\bin\debug (o bin\release según la configuración del proyecto). Copie NumberGuessWorkflowActivities.dll y péguelo en la carpeta PreviousVersions.
Cambie el nombre NumberGuessWorkflowActivities.dll en la carpeta PreviousVersions a NumberGuessWorkflowActivities_v1.dll.
Nota
En los pasos de este tema se muestra una manera de administrar los ensamblados usados para contener varias versiones de los flujos de trabajo. También se pueden usar otros métodos, como el nombre seguro de los ensamblados y su registro en la memoria caché global de ensamblados.
Cree una carpeta denominada NumberGuessWorkflowActivities_du en la misma carpeta que NumberGuessWorkflowHost, NumberGuessWorkflowActivities y la carpeta PreviousVersions recién agregada y agregue todos los archivos y subcarpetas de la carpeta NumberGuessWorkflowActivities a la carpeta NumberGuessWorkflowActivities_du nueva. Esta copia de seguridad del proyecto de la versión inicial de las actividades se usa en Procedimiento para actualizar la definición de una instancia de flujo de trabajo en ejecución.
Vuelva a abrir la solución WF45GettingStartedTutorial en Visual Studio 2012.
Para actualizar el flujo de trabajo
En esta sección, se actualizan las definiciones de flujo de trabajo. Se actualizan las dos actividades de WriteLine
que proporcionan informes sobre los intentos del usuario, y se agrega una nueva actividad WriteLine
que proporciona información adicional sobre el juego una vez se ha adivinado el número.
Para actualizar el flujo de trabajo StateMachine
En el Explorador de soluciones, en el proyecto NumberGuessWorkflowActivities, haga doble clic en StateMachineNumberGuessWorkflow.xaml.
Haga doble clic en la transición Intento incorrecto en la máquina de estados.
Actualice
Text
deWriteLine
del extremo izquierdo en la actividadIf
.Guess & " is too low."
Guess + " is too low."
Actualice
Text
deWriteLine
del extremo derecho en la actividadIf
.Guess & " is too high."
Guess + " is too high."
Vuelva a la vista global de la máquina de estados en el diseñador de flujo de trabajo; para ello, haga clic en StateMachine en la pantalla de la ruta de navegación en la parte superior del diseñador de flujo de trabajo.
Haga doble clic en la transición Intento correcto en la máquina de estados.
Arrastre una actividad WriteLine de la sección Elementos primitivos del Cuadro de herramientas y colóquela sobre la etiqueta Coloque la actividad Action aquí de la transición.
Escriba la siguiente expresión en el cuadro de propiedad
Text
.Guess & " is correct. You guessed it in " & Turns & " turns."
Guess + " is correct. You guessed it in " + Turns + " turns."
Para actualizar el flujo de trabajo Diagrama de flujo
En el Explorador de soluciones, en el proyecto NumberGuessWorkflowActivities, haga doble clic en FlowchartNumberGuessWorkflow.xaml.
Actualice
Text
de la actividadWriteLine
del extremo izquierdo.Guess & " is too low."
Guess + " is too low."
Actualice
Text
de la actividadWriteLine
del extremo derecho.Guess & " is too high."
Guess + " is too high."
Arrastre una actividad WriteLine de la sección Elementos primitivos del Cuadro de herramientas y colóquela en el punto de colocación de la acción
True
deFlowDecision
superior. La actividadWriteLine
se agrega al diagrama de flujo y se vincula a la acciónTrue
deFlowDecision
.Escriba la siguiente expresión en el cuadro de propiedad
Text
.Guess & " is correct. You guessed it in " & Turns & " turns."
Guess + " is correct. You guessed it in " + Turns + " turns."
Para actualizar el flujo de trabajo Secuencial
En el Explorador de soluciones, en el proyecto NumberGuessWorkflowActivities, haga doble clic en SequentialNumberGuessWorkflow.xaml.
Actualice
Text
deWriteLine
del extremo izquierdo en la actividadIf
.Guess & " is too low."
Guess + " is too low."
Actualice
Text
de la actividadWriteLine
del extremo derecho en la actividadIf
.Guess & " is too high."
Guess + " is too high."
Arrastre una actividad WriteLine de la sección Elementos primitivos del Cuadro de herramientas y colóquela después de la actividad DoWhile para que WriteLine sea la actividad final en la actividad
Sequence
raíz.Escriba la siguiente expresión en el cuadro de propiedad
Text
.Guess & " is correct. You guessed it in " & Turns & " turns."
Guess + " is correct. You guessed it in " + Turns + " turns."
Para actualizar WorkflowVersionMap a fin de incluir las versiones de flujo de trabajo anteriores
Haga doble clic en WorkflowVersionMap.cs (o WorkflowVersionMap.vb) del proyecto NumberGuessWorkflowHost para abrirlo.
Agregue las siguientes instrucciones
using
(oImports
) al principio del archivo con las demás instruccionesusing
(oImports
).Imports System.Reflection Imports System.IO
using System.Reflection; using System.IO;
Agregue tres nuevas identidades de flujo de trabajo justo debajo de las tres declaraciones de identidad de flujo de trabajo existentes. Estas nuevas identidades de flujo de trabajo de
v1
se usarán para proporcionar la definición de flujo de trabajo correcta a los flujos de trabajo iniciados antes de que se realizaran las actualizaciones.'Current version identities. Public StateMachineNumberGuessIdentity As WorkflowIdentity Public FlowchartNumberGuessIdentity As WorkflowIdentity Public SequentialNumberGuessIdentity As WorkflowIdentity 'v1 Identities. Public StateMachineNumberGuessIdentity_v1 As WorkflowIdentity Public FlowchartNumberGuessIdentity_v1 As WorkflowIdentity Public SequentialNumberGuessIdentity_v1 As WorkflowIdentity
// Current version identities. static public WorkflowIdentity StateMachineNumberGuessIdentity; static public WorkflowIdentity FlowchartNumberGuessIdentity; static public WorkflowIdentity SequentialNumberGuessIdentity; // v1 identities. static public WorkflowIdentity StateMachineNumberGuessIdentity_v1; static public WorkflowIdentity FlowchartNumberGuessIdentity_v1; static public WorkflowIdentity SequentialNumberGuessIdentity_v1;
En el constructor
WorkflowVersionMap
, actualice la propiedadVersion
de las tres identidades de flujo de trabajo actuales a2.0.0.0
.'Add the current workflow version identities. StateMachineNumberGuessIdentity = New WorkflowIdentity With { .Name = "StateMachineNumberGuessWorkflow", .Version = New Version(2, 0, 0, 0) } FlowchartNumberGuessIdentity = New WorkflowIdentity With { .Name = "FlowchartNumberGuessWorkflow", .Version = New Version(2, 0, 0, 0) } SequentialNumberGuessIdentity = New WorkflowIdentity With { .Name = "SequentialNumberGuessWorkflow", .Version = New Version(2, 0, 0, 0) } map.Add(StateMachineNumberGuessIdentity, New StateMachineNumberGuessWorkflow()) map.Add(FlowchartNumberGuessIdentity, New FlowchartNumberGuessWorkflow()) map.Add(SequentialNumberGuessIdentity, New SequentialNumberGuessWorkflow())
// Add the current workflow version identities. StateMachineNumberGuessIdentity = new WorkflowIdentity { Name = "StateMachineNumberGuessWorkflow", // Version = new Version(1, 0, 0, 0), Version = new Version(2, 0, 0, 0) }; FlowchartNumberGuessIdentity = new WorkflowIdentity { Name = "FlowchartNumberGuessWorkflow", // Version = new Version(1, 0, 0, 0), Version = new Version(2, 0, 0, 0) }; SequentialNumberGuessIdentity = new WorkflowIdentity { Name = "SequentialNumberGuessWorkflow", // Version = new Version(1, 0, 0, 0), Version = new Version(2, 0, 0, 0) }; map.Add(StateMachineNumberGuessIdentity, new StateMachineNumberGuessWorkflow()); map.Add(FlowchartNumberGuessIdentity, new FlowchartNumberGuessWorkflow()); map.Add(SequentialNumberGuessIdentity, new SequentialNumberGuessWorkflow());
El código que agrega las versiones actuales de los flujos de trabajo al diccionario usa las versiones actuales a las que se hace referencia en el proyecto, por lo que no es necesario actualizar el código que inicializa las definiciones de flujo de trabajo.
Agregue el código siguiente en el constructor justo después del código que agrega las versiones actuales al diccionario.
'Initialize the previous workflow version identities. StateMachineNumberGuessIdentity_v1 = New WorkflowIdentity With { .Name = "StateMachineNumberGuessWorkflow", .Version = New Version(1, 0, 0, 0) } FlowchartNumberGuessIdentity_v1 = New WorkflowIdentity With { .Name = "FlowchartNumberGuessWorkflow", .Version = New Version(1, 0, 0, 0) } SequentialNumberGuessIdentity_v1 = New WorkflowIdentity With { .Name = "SequentialNumberGuessWorkflow", .Version = New Version(1, 0, 0, 0) }
// Initialize the previous workflow version identities. StateMachineNumberGuessIdentity_v1 = new WorkflowIdentity { Name = "StateMachineNumberGuessWorkflow", Version = new Version(1, 0, 0, 0) }; FlowchartNumberGuessIdentity_v1 = new WorkflowIdentity { Name = "FlowchartNumberGuessWorkflow", Version = new Version(1, 0, 0, 0) }; SequentialNumberGuessIdentity_v1 = new WorkflowIdentity { Name = "SequentialNumberGuessWorkflow", Version = new Version(1, 0, 0, 0) };
Estas identidades de flujo de trabajo están asociadas a las versiones iniciales de las definiciones de flujo de trabajo correspondientes.
A continuación, cargue el ensamblado que contiene la versión inicial de las definiciones de flujo de trabajo, y cree y agregue las definiciones de flujo de trabajo al diccionario.
'Add the previous version workflow identities to the dictionary along with 'the corresponding workflow definitions loaded from the v1 assembly. 'Assembly.LoadFile requires an absolute path so convert this relative path 'to an absolute path. Dim v1AssemblyPath As String = "..\..\..\PreviousVersions\NumberGuessWorkflowActivities_v1.dll" v1AssemblyPath = Path.GetFullPath(v1AssemblyPath) Dim v1Assembly As Assembly = Assembly.LoadFile(v1AssemblyPath) map.Add(StateMachineNumberGuessIdentity_v1, v1Assembly.CreateInstance("NumberGuessWorkflowActivities.StateMachineNumberGuessWorkflow")) map.Add(SequentialNumberGuessIdentity_v1, v1Assembly.CreateInstance("NumberGuessWorkflowActivities.SequentialNumberGuessWorkflow")) map.Add(FlowchartNumberGuessIdentity_v1, v1Assembly.CreateInstance("NumberGuessWorkflowActivities.FlowchartNumberGuessWorkflow"))
// Add the previous version workflow identities to the dictionary along with // the corresponding workflow definitions loaded from the v1 assembly. // Assembly.LoadFile requires an absolute path so convert this relative path // to an absolute path. string v1AssemblyPath = @"..\..\..\PreviousVersions\NumberGuessWorkflowActivities_v1.dll"; v1AssemblyPath = Path.GetFullPath(v1AssemblyPath); Assembly v1Assembly = Assembly.LoadFile(v1AssemblyPath); map.Add(StateMachineNumberGuessIdentity_v1, v1Assembly.CreateInstance("NumberGuessWorkflowActivities.StateMachineNumberGuessWorkflow") as Activity); map.Add(SequentialNumberGuessIdentity_v1, v1Assembly.CreateInstance("NumberGuessWorkflowActivities.SequentialNumberGuessWorkflow") as Activity); map.Add(FlowchartNumberGuessIdentity_v1, v1Assembly.CreateInstance("NumberGuessWorkflowActivities.FlowchartNumberGuessWorkflow") as Activity);
En el ejemplo siguiente se muestra la lista completa para la clase
WorkflowVersionMap
actualizada.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 'v1 Identities. Public StateMachineNumberGuessIdentity_v1 As WorkflowIdentity Public FlowchartNumberGuessIdentity_v1 As WorkflowIdentity Public SequentialNumberGuessIdentity_v1 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(2, 0, 0, 0) } FlowchartNumberGuessIdentity = New WorkflowIdentity With { .Name = "FlowchartNumberGuessWorkflow", .Version = New Version(2, 0, 0, 0) } SequentialNumberGuessIdentity = New WorkflowIdentity With { .Name = "SequentialNumberGuessWorkflow", .Version = New Version(2, 0, 0, 0) } map.Add(StateMachineNumberGuessIdentity, New StateMachineNumberGuessWorkflow()) map.Add(FlowchartNumberGuessIdentity, New FlowchartNumberGuessWorkflow()) map.Add(SequentialNumberGuessIdentity, New SequentialNumberGuessWorkflow()) 'Initialize the previous workflow version identities. StateMachineNumberGuessIdentity_v1 = New WorkflowIdentity With { .Name = "StateMachineNumberGuessWorkflow", .Version = New Version(1, 0, 0, 0) } FlowchartNumberGuessIdentity_v1 = New WorkflowIdentity With { .Name = "FlowchartNumberGuessWorkflow", .Version = New Version(1, 0, 0, 0) } SequentialNumberGuessIdentity_v1 = New WorkflowIdentity With { .Name = "SequentialNumberGuessWorkflow", .Version = New Version(1, 0, 0, 0) } 'Add the previous version workflow identities to the dictionary along with 'the corresponding workflow definitions loaded from the v1 assembly. 'Assembly.LoadFile requires an absolute path so convert this relative path 'to an absolute path. Dim v1AssemblyPath As String = "..\..\..\PreviousVersions\NumberGuessWorkflowActivities_v1.dll" v1AssemblyPath = Path.GetFullPath(v1AssemblyPath) Dim v1Assembly As Assembly = Assembly.LoadFile(v1AssemblyPath) map.Add(StateMachineNumberGuessIdentity_v1, v1Assembly.CreateInstance("NumberGuessWorkflowActivities.StateMachineNumberGuessWorkflow")) map.Add(SequentialNumberGuessIdentity_v1, v1Assembly.CreateInstance("NumberGuessWorkflowActivities.SequentialNumberGuessWorkflow")) map.Add(FlowchartNumberGuessIdentity_v1, v1Assembly.CreateInstance("NumberGuessWorkflowActivities.FlowchartNumberGuessWorkflow")) 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; // v1 identities. static public WorkflowIdentity StateMachineNumberGuessIdentity_v1; static public WorkflowIdentity FlowchartNumberGuessIdentity_v1; static public WorkflowIdentity SequentialNumberGuessIdentity_v1; 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), Version = new Version(2, 0, 0, 0) }; FlowchartNumberGuessIdentity = new WorkflowIdentity { Name = "FlowchartNumberGuessWorkflow", // Version = new Version(1, 0, 0, 0), Version = new Version(2, 0, 0, 0) }; SequentialNumberGuessIdentity = new WorkflowIdentity { Name = "SequentialNumberGuessWorkflow", // Version = new Version(1, 0, 0, 0), Version = new Version(2, 0, 0, 0) }; map.Add(StateMachineNumberGuessIdentity, new StateMachineNumberGuessWorkflow()); map.Add(FlowchartNumberGuessIdentity, new FlowchartNumberGuessWorkflow()); map.Add(SequentialNumberGuessIdentity, new SequentialNumberGuessWorkflow()); // Initialize the previous workflow version identities. StateMachineNumberGuessIdentity_v1 = new WorkflowIdentity { Name = "StateMachineNumberGuessWorkflow", Version = new Version(1, 0, 0, 0) }; FlowchartNumberGuessIdentity_v1 = new WorkflowIdentity { Name = "FlowchartNumberGuessWorkflow", Version = new Version(1, 0, 0, 0) }; SequentialNumberGuessIdentity_v1 = new WorkflowIdentity { Name = "SequentialNumberGuessWorkflow", Version = new Version(1, 0, 0, 0) }; // Add the previous version workflow identities to the dictionary along with // the corresponding workflow definitions loaded from the v1 assembly. // Assembly.LoadFile requires an absolute path so convert this relative path // to an absolute path. string v1AssemblyPath = @"..\..\..\PreviousVersions\NumberGuessWorkflowActivities_v1.dll"; v1AssemblyPath = Path.GetFullPath(v1AssemblyPath); Assembly v1Assembly = Assembly.LoadFile(v1AssemblyPath); map.Add(StateMachineNumberGuessIdentity_v1, v1Assembly.CreateInstance("NumberGuessWorkflowActivities.StateMachineNumberGuessWorkflow") as Activity); map.Add(SequentialNumberGuessIdentity_v1, v1Assembly.CreateInstance("NumberGuessWorkflowActivities.SequentialNumberGuessWorkflow") as Activity); map.Add(FlowchartNumberGuessIdentity_v1, v1Assembly.CreateInstance("NumberGuessWorkflowActivities.FlowchartNumberGuessWorkflow") as Activity); } public static Activity GetWorkflowDefinition(WorkflowIdentity identity) { return map[identity]; } public static string GetIdentityDescription(WorkflowIdentity identity) { return identity.ToString(); } }
Para generar y ejecutar la aplicación
Presione CTRL+MAYÚS+B para compilar la aplicación y, a continuación, CTRL+F5 para iniciarla.
Haga clic en Nuevo juego para iniciar un flujo de trabajo nuevo. La versión del flujo de trabajo se muestra debajo de la ventana de estado y refleja la versión actualizada del
WorkflowIdentity
asociado. Anote el valor deInstanceId
para poder ver el archivo de seguimiento del flujo de trabajo cuando se complete y, a continuación, escriba números hasta que se termine el juego. Observe cómo el intento del usuario aparece en la información que se muestra en la ventana de estado en función de las actualizaciones de las actividadesWriteLine
.Please enter a number between 1 and 10 5 is too high. Please enter a number between 1 and 10 3 is too high. Please enter a number between 1 and 10 1 is too low. Please enter a number between 1 and 10 Congratulations, you guessed the number in 4 turns.
Nota
Se muestra el texto actualizado de las actividades
WriteLine
, pero no se muestra el resultado de la actividad finalWriteLine
que se agregó en este tema. Esto se debe a que el controladorPersistableIdle
actualiza la ventana de estado. Debido a que el flujo de trabajo se completa y no queda inactivo después de la actividad final, no se llama al controladorPersistableIdle
. Sin embargo, el controladorCompleted
muestra un mensaje similar en la ventana de estado. Si se desea, se puede agregar un código al controladorCompleted
para extraer el texto deStringWriter
y mostrarlo en la ventana de estado.Abra el Explorador de Windows y navegue a la carpeta NumberGuessWorkflowHost\bin\debug (o bin\release en función de la configuración del proyecto) y abra el archivo de seguimiento mediante el Bloc de notas que corresponde al flujo de trabajo completado. Si no anotó
InstanceId
, puede identificar el archivo de seguimiento correcto mediante la información de Fecha de modificación en el Explorador de Windows.Please enter a number between 1 and 10 5 is too high. Please enter a number between 1 and 10 3 is too high. Please enter a number between 1 and 10 1 is too low. Please enter a number between 1 and 10 2 is correct. You guessed it in 4 turns.
La salida de
WriteLine
actualizada se encuentra en el archivo de seguimiento, incluida la salida deWriteLine
que se agregó en este tema.Vuelva a la aplicación para adivinar números y seleccione uno de los flujos de trabajo iniciado antes de que se realizaran las actualizaciones. Puede identificar la versión del flujo de trabajo seleccionado actualmente si examina la información de versión que aparece debajo de la ventana de estado. Escriba los números y observe que las actualizaciones de estado coinciden con el resultado de la actividad
WriteLine
de la versión anterior y no incluyen el intento del usuario. Esto se debe a que estos flujos de trabajo usan la definición de flujo de trabajo anterior que no tiene las actualizacionesWriteLine
.En el paso siguiente, Procedimiento para actualizar la definición de una instancia de flujo de trabajo en ejecución, las instancias del flujo de trabajo
v1
en ejecución se actualizan para que puedan contener la funcionalidad nueva como las instanciasv2
.