Nota
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
Los servicios de flujo de trabajo y los clientes pueden participar en transacciones. Para que una operación de servicio forme parte de una transacción ambiental, coloque una Receive actividad dentro de una TransactedReceiveScope actividad. En cualquier llamada realizada por un objeto Send o una actividad de SendReply dentro de TransactedReceiveScope también se realizará dentro de la transacción de ambiente. Una aplicación cliente del flujo de trabajo puede crear una transacción de ambiente utilizando la actividad de TransactionScope y operaciones de servicio de llamada que usen la transacción de ambiente. Este tema le guía a través de la creación de un servicio de flujo de trabajo y un cliente de flujo de trabajo que participan en transacciones.
Advertencia
Si una instancia de servicio de flujo de trabajo se carga dentro de una transacción y el flujo de trabajo contiene una Persist actividad, la instancia de flujo de trabajo se bloqueará hasta que se agote el tiempo de espera de la transacción.
Importante
Siempre que use un objeto TransactedReceiveScope se recomienda que coloque todas las recepciones en el flujo de trabajo dentro de actividades TransactedReceiveScope.
Importante
Al usar TransactedReceiveScope y los mensajes llegan en el orden incorrecto, el flujo de trabajo se anulará al intentar entregar el primer mensaje desordenado. Debe asegurarse de que el flujo de trabajo siempre está en un punto de detención coherente cuando el flujo de trabajo está inactivo. Esto le permitirá reiniciar el flujo de trabajo desde un punto de persistencia anterior si se anula el flujo de trabajo.
Creación de una biblioteca compartida
Cree una nueva solución vacía de Visual Studio.
Agregue un nuevo proyecto de biblioteca de clases denominado
Common
. Agregue referencias a los ensamblados siguientes:System.Activities.dll
System.ServiceModel.dll
System.ServiceModel.Activities.dll
System.Transactions.dll
Agregue una nueva clase llamada
PrintTransactionInfo
alCommon
proyecto. Esta clase se deriva de NativeActivity y sobrecarga el Execute método .using System; using System; using System.Activities; using System.Transactions; namespace Common { public class PrintTransactionInfo : NativeActivity { protected override void Execute(NativeActivityContext context) { RuntimeTransactionHandle rth = context.Properties.Find(typeof(RuntimeTransactionHandle).FullName) as RuntimeTransactionHandle; if (rth == null) { Console.WriteLine("There is no ambient RuntimeTransactionHandle"); } Transaction t = rth.GetCurrentTransaction(context); if (t == null) { Console.WriteLine("There is no ambient transaction"); } else { Console.WriteLine("Transaction: {0} is {1}", t.TransactionInformation.DistributedIdentifier, t.TransactionInformation.Status); } } } }
Se trata de una actividad nativa que muestra información sobre la transacción ambiental y se usa en los flujos de trabajo de servicio y cliente usados en este tema. Compile la solución para que esta actividad esté disponible en la sección Común del Cuadro de herramientas.
Implementación del servicio de flujo de trabajo
Agregue un nuevo servicio de flujo de trabajo WCF, llamado
WorkflowService
al proyectoCommon
. Para ello, haga clic con el botón derecho en elCommon
proyecto, seleccione Agregar, Nuevo elemento ..., Seleccione Flujo de trabajo en Plantillas instaladas y seleccione Servicio de flujo de trabajo de WCF.Elimine las actividades predeterminadas
ReceiveRequest
ySendResponse
.Arrastre y coloque una actividad de WriteLine en la actividad de
Sequential Service
. Establezca la propiedad de texto en"Workflow Service starting ..."
, como se muestra en el ejemplo siguiente.![Incorporación de una actividad WriteLine a la actividad de servicio secuencial(./media/flow-transactions-into-and-out-of-workflow-services/add-writeline-sequential-service.jpg)
Arrastre y coloque una actividad TransactedReceiveScope después de la actividad de WriteLine. La TransactedReceiveScope actividad se puede encontrar en la sección Mensajería del Cuadro de herramientas. La TransactedReceiveScope actividad se compone de dos secciones Request y Body. La sección Solicitud contiene la Receive actividad. La sección Cuerpo contiene las actividades que se van a ejecutar dentro de una transacción después de recibir un mensaje.
Seleccione la TransactedReceiveScope actividad y haga clic en el botón Variables . Agregue las variables siguientes.
Nota:
Puede eliminar la variable de datos que está allí de forma predeterminada. También puede utilizar la variable de controlador existente.
Arrastre y coloque una actividad Receive dentro de la sección Solicitud de la actividad TransactedReceiveScope. Establezca las siguientes propiedades:
Propiedad Importancia CanCreateInstance Verdadero (marque la casilla) NombreDeOperación StartSample NombreDelContratoDeServicio ITransactionSample El flujo de trabajo debe tener este aspecto:
Haga clic en el vínculo Definir... de la Receive actividad y haga lo siguiente:
Arrastre y coloque una actividad de Sequence en la sección Cuerpo de TransactedReceiveScope. Dentro de la actividad de Sequence, arrastre las dos actividades de WriteLine y establezca las propiedades Text como se muestra en la siguiente tabla.
Actividad Importancia Primera propiedad WriteLine "Servicio: recepción completada" Segunda propiedad WriteLine "Servicio: recibido = " + requestMessage El flujo de trabajo debería tener este aspecto:
Arrastre y coloque la actividad
PrintTransactionInfo
después de la segunda actividad WriteLine en la sección Cuerpo de la actividad TransactedReceiveScope.Arrastre y coloque una Assign actividad después de la
PrintTransactionInfo
actividad y establezca sus propiedades según la tabla siguiente.Propiedad Importancia En mensaje de respuesta Importancia "Servicio: Envío de respuesta." Arrastre y coloque una actividad de WriteLine después de la actividad de Assign y establezca su propiedad Text en "Servicio: iniciar respuesta".
El flujo de trabajo debería tener este aspecto:
Haga clic con el botón derecho en la Receive actividad y seleccione Crear SendReply y péguela después de la última WriteLine actividad. Haga clic en el vínculo Definir... de la
SendReplyToReceive
actividad y haga lo siguiente.Arrastra y suelta una actividad WriteLine después de la actividad
SendReplyToReceive
y establece su propiedad Text en "Servicio: Respuesta enviada".Arrastre y coloque una WriteLine actividad en la parte inferior del flujo de trabajo y establezca su Text propiedad en "Servicio: Finaliza el flujo de trabajo, presione ENTRAR para salir".
El flujo de trabajo de servicio completado debe tener este aspecto:
Implementación del cliente de flujo de trabajo
Agregue una nueva aplicación de flujo de trabajo de WCF, denominada
WorkflowClient
alCommon
proyecto. Para ello, haga clic con el botón derecho en elCommon
proyecto, seleccione Agregar, Nuevo elemento ..., Seleccione Flujo de trabajo en Plantillas instaladas y seleccione Actividad.Arrastre y coloque una actividad Sequence en la superficie de diseño.
Dentro de la actividad Sequence, arrastre y coloque la actividad WriteLine y establezca su propiedad Text a
"Client: Workflow starting"
. El flujo de trabajo debería tener este aspecto:Arrastre y coloque una actividad de TransactionScope después de la actividad de WriteLine. Seleccione la TransactionScope actividad, haga clic en el botón Variables y agregue las siguientes variables.
Arrastre y coloque una actividad de Sequence en el cuerpo de la actividad de TransactionScope.
Arrastre y coloque una actividad de
PrintTransactionInfo
dentro de Sequence.Arrastre y coloque una actividad WriteLine después de la actividad
PrintTransactionInfo
y establezca su propiedad Text en "Cliente: comenzando envío". El flujo de trabajo debería tener este aspecto:Arrastre y coloque una Send actividad después de la Assign actividad y establezca las siguientes propiedades:
Propiedad Importancia EndpointConfigurationName workflowServiceEndpoint NombreDeOperación StartSample NombreDelContratoDeServicio ITransactionSample El flujo de trabajo debería tener este aspecto:
Haga clic en el vínculo Definir... y haga lo siguiente:
Haga clic con el botón derecho en la Send actividad y seleccione Crear receiveReply. La ReceiveReply actividad se colocará automáticamente después de la Send actividad.
Haga clic en Definir... vínculo en la actividad ReceiveReplyForSend y realice la siguiente configuración:
Arrastre y coloque una actividad de WriteLine entre las actividades de Send y ReceiveReply, y establezca su propiedad Text en "Cliente: envío completado".
Arrastre y coloque una actividad de WriteLine después de la actividad de ReceiveReply y establezca su propiedad Text en "Cliente: respuesta recibida = " + replyMessage
Arrastre y coloque una actividad de
PrintTransactionInfo
después de la actividad de WriteLine.Arrastre y coloque una WriteLine actividad al final del flujo de trabajo y establezca su Text propiedad en "Finalizar el flujo de trabajo de cliente". El flujo de trabajo de cliente completado debe ser similar al diagrama siguiente.
Compile la solución.
Creación de la aplicación de servicio
Agregue un nuevo proyecto de aplicación de consola llamado
Service
a la solución. Agregue referencias a los ensamblados siguientes:System.Activities.dll
System.ServiceModel.dll
System.ServiceModel.Activities.dll
Abra el archivo Program.cs generado y el código siguiente:
static void Main() { Console.WriteLine("Building the server."); using (WorkflowServiceHost host = new WorkflowServiceHost(new DeclarativeServiceWorkflow(), new Uri("net.tcp://localhost:8000/TransactedReceiveService/Declarative"))) { //Start the server host.Open(); Console.WriteLine("Service started."); Console.WriteLine(); Console.ReadLine(); //Shutdown host.Close(); }; }
Agregue el siguiente archivo app.config al proyecto.
<?xml version="1.0" encoding="utf-8" ?> <!-- Copyright © Microsoft Corporation. All rights reserved. --> <configuration> <system.serviceModel> <bindings> <netTcpBinding> <binding transactionFlow="true" /> </netTcpBinding> </bindings> </system.serviceModel> </configuration>
Creación de la aplicación cliente
Agregue un nuevo proyecto de aplicación de consola llamado
Client
a la solución. Agregue una referencia a System.Activities.dll.Abra el archivo program.cs y agregue el código siguiente.
class Program { private static AutoResetEvent syncEvent = new AutoResetEvent(false); static void Main(string[] args) { //Build client Console.WriteLine("Building the client."); WorkflowApplication client = new WorkflowApplication(new DeclarativeClientWorkflow()); client.Completed = Program.Completed; client.Aborted = Program.Aborted; client.OnUnhandledException = Program.OnUnhandledException; //Wait for service to start Console.WriteLine("Press ENTER once service is started."); Console.ReadLine(); //Start the client Console.WriteLine("Starting the client."); client.Run(); syncEvent.WaitOne(); //Sample complete Console.WriteLine(); Console.WriteLine("Client complete. Press ENTER to exit."); Console.ReadLine(); } private static void Completed(WorkflowApplicationCompletedEventArgs e) { Program.syncEvent.Set(); } private static void Aborted(WorkflowApplicationAbortedEventArgs e) { Console.WriteLine("Client Aborted: {0}", e.Reason); Program.syncEvent.Set(); } private static UnhandledExceptionAction OnUnhandledException(WorkflowApplicationUnhandledExceptionEventArgs e) { Console.WriteLine("Client had an unhandled exception: {0}", e.UnhandledException); return UnhandledExceptionAction.Cancel; } }