Compartir a través de


Cómo: Ejecutar un flujo de trabajo

Este tema es aplicable a Windows Workflow Foundation 4.

Este tema es una continuación del tutorial introductorio de Windows Workflow Foundation y explica cómo ejecutar el flujo de trabajo definido en el tema anterior Cómo: Crear flujos de trabajo.

Dd489463.note(es-es,VS.100).gifNota:
Cada uno de los temas del tutorial de introducción depende de los temas anteriores. Para completar este tema, primero debe finalizar Cómo: Crear una actividad y Cómo: Crear flujos de trabajo.

Para abrir el proyecto de host de flujo de trabajo

  1. Abra la solución del tema anterior Cómo: Crear flujos de trabajo con Visual Studio 2010.

  2. Haga doble clic en Program.cs o en Module1.vb en el Explorador de soluciones para mostrar el código.

    Dd489463.Tip(es-es,VS.100).gifSugerencia:
    Si la ventana Explorador de soluciones no se muestra, seleccione Explorador de soluciones en el menú Ver.

    Dado que este proyecto se creó con la plantilla Aplicación de consola de flujos de trabajos, Program.cs o Module1.vb, contiene el siguiente código básico de hospedaje de flujo de trabajo.

    WorkflowInvoker.Invoke(New Workflow1())
    
    WorkflowInvoker.Invoke(new Workflow1());
    

    Este código de hospedaje generado usa WorkflowInvoker. WorkflowInvoker proporciona una manera sencilla de invocar un flujo de trabajo como si fuera una llamada de método y solo pueden usarlo flujos de trabajo que no usan la persistencia. WorkflowApplication proporciona un modelo más enriquecido para ejecutar flujos de trabajo que incluye notificación de eventos de ciclo de vida, control de ejecución, reanudación de marcadores y persistencia. Este ejemplo usa marcadores y WorkflowApplication se usa para hospedar el flujo de trabajo. Agregue la siguiente instrucción using o Imports al principio de Program.cs o Module1.vb debajo de las instrucciones using oImports existentes.

    Imports System.Threading
    
    using System.Threading;
    

    Reemplace la línea de código que usa WorkflowInvoker con el siguiente código básico de hospedaje WorkflowApplication. Este código de hospedaje de ejemplo muestra los pasos básicos para hospedar e invocar un flujo de trabajo, pero no contiene, sin embargo, la funcionalidad necesaria para ejecutar correctamente el flujo de trabajo en este tema. En los pasos que figuran a continuación, el código básico se modifica y se agregan características adicionales hasta completar la aplicación.

    Dim syncEvent As New AutoResetEvent(False)
    
    Dim wfApp As New WorkflowApplication(New Workflow1())
    
    wfApp.Completed = _
        Sub(e As WorkflowApplicationCompletedEventArgs)
            syncEvent.Set()
        End Sub
    
    wfApp.Aborted = _
        Sub(e As WorkflowApplicationAbortedEventArgs)
            Console.WriteLine(e.Reason)
            syncEvent.Set()
        End Sub
    
    wfApp.OnUnhandledException = _
        Function(e As WorkflowApplicationUnhandledExceptionEventArgs)
            Console.WriteLine(e.UnhandledException)
            Return UnhandledExceptionAction.Terminate
        End Function
    
    wfApp.Run()
    
    syncEvent.WaitOne()
    
    AutoResetEvent syncEvent = new AutoResetEvent(false);
    
    WorkflowApplication wfApp =
        new WorkflowApplication(new Workflow1());
    
    wfApp.Completed = delegate(WorkflowApplicationCompletedEventArgs e)
    {
        syncEvent.Set();
    };
    
    wfApp.Aborted = delegate(WorkflowApplicationAbortedEventArgs e)
    {
        Console.WriteLine(e.Reason);
        syncEvent.Set();
    };
    
    wfApp.OnUnhandledException = delegate(WorkflowApplicationUnhandledExceptionEventArgs e)
    {
        Console.WriteLine(e.UnhandledException.ToString());
        return UnhandledExceptionAction.Terminate;
    };
    
    wfApp.Run();
    
    syncEvent.WaitOne();
    

    Este código crea un objetoWorkflowApplication, se suscribe a tres eventos de ciclo de vida de flujo de trabajo, inicia el flujo de trabajo con una llamada a Run y espera a que el flujo de trabajo se complete. Cuando el flujo de trabajo finaliza, se establece AutoResetEvent y se completa la aplicación host.

Para definir argumentos de entrada de un flujo de trabajo

  1. Agregue la siguiente instrucción al principio de Program.cs o Module1.vb debajo de las instrucciones using o Imports existentes.

    Imports System.Collections.Generic
    
    using System.Collections.Generic;
    
  2. Reemplace la línea de código que crea el nuevo WorkflowApplication con el siguiente código que crea y pasa un diccionario de parámetros al flujo de trabajo cuando se crea.

    Dim inputs As New Dictionary(Of String, Object)
    inputs.Add("MaxNumber", 100)
    
    Dim wfApp As New WorkflowApplication(New Workflow1(), inputs)
    
    var inputs = new Dictionary<string, object>() { { "MaxNumber", 100 } };
    
    WorkflowApplication wfApp =
        new WorkflowApplication(new Workflow1(), inputs);
    

    Este diccionario contiene un elemento con una clave de MaxNumber. Las claves del diccionario de entrada se corresponden con los argumentos de entrada en la actividad raíz del flujo de trabajo. El flujo de trabajo usa MaxNumber para determinar el límite superior para el número generado de forma aleatoria.

Para recuperar parámetros de salida de un flujo de trabajo

  1. Modifique el controlador Completed para recuperar y mostrar el número de intentos que usó el flujo de trabajo.

    wfApp.Completed = _
        Sub(e As WorkflowApplicationCompletedEventArgs)
            Dim Turns As Integer = Convert.ToInt32(e.Outputs("Turns"))
            Console.WriteLine("Congratulations, you guessed the number in {0} turns.", Turns)
    
            syncEvent.Set()
        End Sub
    
    wfApp.Completed = delegate(WorkflowApplicationCompletedEventArgs e)
    {
        int Turns = Convert.ToInt32(e.Outputs["Turns"]);
        Console.WriteLine("Congratulations, you guessed the number in {0} turns.", Turns);
    
        syncEvent.Set();
    };
    

Para reanudar un marcador

  1. Agregue el siguiente código en la parte superior del método Main justo después de la declaración AutoResetEvent existente.

    Dim idleEvent As New AutoResetEvent(False)
    
    AutoResetEvent idleEvent = new AutoResetEvent(false);
    
  2. Agregue el siguiente controlador Idle justo después de los tres controladores de ciclo de vida de flujo de trabajo existentes en Main.

    wfApp.Idle = _
        Sub(e As WorkflowApplicationIdleEventArgs)
            idleEvent.Set()
        End Sub
    
    wfApp.Idle = delegate(WorkflowApplicationIdleEventArgs e)
    {
        idleEvent.Set();
    };
    

    Cada vez que el flujo de trabajo se vuelve inactivo a la espera de la siguiente suposición, se llama a este controlador y se establece idleActionAutoResetEvent. El código en el siguiente paso usa idleEvent y syncEvent para determinar si el flujo de trabajo está esperando la siguiente suposición o si se ha completado.

    Dd489463.note(es-es,VS.100).gifNota:
    En este ejemplo, la aplicación host usa eventos de restablecimiento automático en los controladores Idle y Completed para sincronizar la aplicación host con el progreso del flujo de trabajo. No es necesario bloquear y esperar a que el flujo de trabajo se vuelva inactivo para reanudar un marcador, aunque en este ejemplo los eventos de sincronización resultan necesarios para que el host sepa si se ha completado el flujo de trabajo o si está esperando más entradas de usuario mediante Bookmark. Para obtener más información, vea Marcadores.

  3. Quite la llamada a WaitOney reemplácela con código para recopilar la entrada del usuario y reanudar el marcador Bookmark.

    Quite la siguiente línea de código.

    syncEvent.WaitOne()
    
    syncEvent.WaitOne();
    

    Reemplácela con el siguiente ejemplo.

    ' Loop until the workflow completes.
    Dim waitHandles As WaitHandle() = New WaitHandle() {syncEvent, idleEvent}
    Do While WaitHandle.WaitAny(waitHandles) <> 0
        'Gather the user input and resume the bookmark.
        Dim validEntry As Boolean = False
        Do While validEntry = False
            Dim Guess As Integer
            If Int32.TryParse(Console.ReadLine(), Guess) = False Then
                Console.WriteLine("Please enter an integer.")
            Else
                validEntry = True
                wfApp.ResumeBookmark("EnterGuess", Guess)
            End If
        Loop
    Loop
    
    // Loop until the workflow completes.
    WaitHandle[] handles = new WaitHandle[] { syncEvent, idleEvent };
    while (WaitHandle.WaitAny(handles) != 0)
    {
        // Gather the user input and resume the bookmark.
        bool validEntry = false;
        while (!validEntry)
        {
            int Guess;
            if (!Int32.TryParse(Console.ReadLine(), out Guess))
            {
                Console.WriteLine("Please enter an integer.");
            }
            else
            {
                validEntry = true;
                wfApp.ResumeBookmark("EnterGuess", Guess);
            }
        }
    }
    

Para compilar y ejecutar la aplicación

  1. Haga clic con el botón secundario en WorkflowConsoleApplication1 en el Explorador de soluciones y seleccione Establecer como proyecto de inicio.

  2. Presione CTRL+F5 para compilar y ejecutar la aplicación. Intente adivinar el número en los menos intentos posibles.

    Para obtener instrucciones sobre cómo agregar la persistencia a una aplicación de flujo de trabajo, vea el siguiente tema, Cómo: Crear y ejecutar un flujo de trabajo de larga ejecución.

Ejemplo

En el ejemplo siguiente se muestra la lista de código completa del método Main.

Sub Main()
    Dim syncEvent As New AutoResetEvent(False)
    Dim idleEvent As New AutoResetEvent(False)

    Dim inputs As New Dictionary(Of String, Object)
    inputs.Add("MaxNumber", 100)

    Dim wfApp As New WorkflowApplication(New Workflow1(), inputs)

    wfApp.Completed = _
        Sub(e As WorkflowApplicationCompletedEventArgs)
            Dim Turns As Integer = Convert.ToInt32(e.Outputs("Turns"))
            Console.WriteLine("Congratulations, you guessed the number in {0} turns.", Turns)

            syncEvent.Set()
        End Sub

    wfApp.Aborted = _
        Sub(e As WorkflowApplicationAbortedEventArgs)
            Console.WriteLine(e.Reason)
            syncEvent.Set()
        End Sub

    wfApp.OnUnhandledException = _
        Function(e As WorkflowApplicationUnhandledExceptionEventArgs)
            Console.WriteLine(e.UnhandledException)
            Return UnhandledExceptionAction.Terminate
        End Function

    wfApp.Idle = _
        Sub(e As WorkflowApplicationIdleEventArgs)
            idleEvent.Set()
        End Sub

    wfApp.Run()

    ' Loop until the workflow completes.
    Dim waitHandles As WaitHandle() = New WaitHandle() {syncEvent, idleEvent}
    Do While WaitHandle.WaitAny(waitHandles) <> 0
        'Gather the user input and resume the bookmark.
        Dim validEntry As Boolean = False
        Do While validEntry = False
            Dim Guess As Integer
            If Int32.TryParse(Console.ReadLine(), Guess) = False Then
                Console.WriteLine("Please enter an integer.")
            Else
                validEntry = True
                wfApp.ResumeBookmark("EnterGuess", Guess)
            End If
        Loop
    Loop
End Sub
static void Main(string[] args)
{
    AutoResetEvent syncEvent = new AutoResetEvent(false);
    AutoResetEvent idleEvent = new AutoResetEvent(false);

    var inputs = new Dictionary<string, object>() { { "MaxNumber", 100 } };

    WorkflowApplication wfApp =
        new WorkflowApplication(new Workflow1(), inputs);

    wfApp.Completed = delegate(WorkflowApplicationCompletedEventArgs e)
    {
        int Turns = Convert.ToInt32(e.Outputs["Turns"]);
        Console.WriteLine("Congratulations, you guessed the number in {0} turns.", Turns);

        syncEvent.Set();
    };

    wfApp.Aborted = delegate(WorkflowApplicationAbortedEventArgs e)
    {
        Console.WriteLine(e.Reason);
        syncEvent.Set();
    };

    wfApp.OnUnhandledException = delegate(WorkflowApplicationUnhandledExceptionEventArgs e)
    {
        Console.WriteLine(e.UnhandledException.ToString());
        return UnhandledExceptionAction.Terminate;
    };

    wfApp.Idle = delegate(WorkflowApplicationIdleEventArgs e)
    {
        idleEvent.Set();
    };

    wfApp.Run();

    // Loop until the workflow completes.
    WaitHandle[] handles = new WaitHandle[] { syncEvent, idleEvent };
    while (WaitHandle.WaitAny(handles) != 0)
    {
        // Gather the user input and resume the bookmark.
        bool validEntry = false;
        while (!validEntry)
        {
            int Guess;
            if (!Int32.TryParse(Console.ReadLine(), out Guess))
            {
                Console.WriteLine("Please enter an integer.");
            }
            else
            {
                validEntry = true;
                wfApp.ResumeBookmark("EnterGuess", Guess);
            }
        }
    }
}

Vea también

Tareas

Cómo: Crear flujos de trabajo
Cómo: Crear y ejecutar un flujo de trabajo de larga ejecución

Referencia

WorkflowApplication
Bookmark

Otros recursos

Programación de Windows Workflow Foundation
Tutorial de introducción
Esperar entrada en un flujo de trabajo
Hospedar flujos de trabajo