Partilhar via


Como: Executar um fluxo de trabalho

Este tópico é uma continuação do tutorial de Introdução do Windows Workflow Foundation e discute como criar um host de fluxo de trabalho e executar o fluxo de trabalho definido no tópico anterior Como criar um fluxo de trabalho .

Nota

Cada tópico no tutorial de Introdução depende dos tópicos anteriores. Para concluir este tópico, você deve primeiro concluir Como: Criar uma atividade e Como: Criar um fluxo de trabalho.

Para criar o projeto de host do fluxo de trabalho

  1. Abra a solução do tópico anterior Como: Criar uma atividade usando o Visual Studio 2012.

  2. Clique com o botão direito do mouse na solução WF45GettingStartedTutorial no Gerenciador de Soluções e selecione Adicionar, Novo Projeto.

    Gorjeta

    Se a janela Gerenciador de Soluções não for exibida, selecione Gerenciador de Soluções no menu Exibir .

  3. No nó Instalado, selecione Visual C#, Workflow (ou Visual Basic, Workflow).

    Nota

    Dependendo de qual linguagem de programação é configurada como a linguagem principal no Visual Studio, o nó Visual C# ou Visual Basic pode estar sob o nó Outras linguagens no nó instalado .

    Verifique se o .NET Framework 4.5 está selecionado na lista suspensa de versão do .NET Framework. Selecione Aplicativo de console de fluxo de trabalho na lista Fluxo de trabalho . Digite NumberGuessWorkflowHost na caixa Nome e clique em OK. Isso cria um aplicativo de fluxo de trabalho inicial com suporte básico de hospedagem de fluxo de trabalho. Esse código básico de hospedagem é modificado e usado para executar o aplicativo de fluxo de trabalho.

  4. Clique com o botão direito do mouse no projeto NumberGuessWorkflowHost recém-adicionado no Gerenciador de Soluções e selecione Adicionar Referência. Selecione Solução na lista Adicionar Referência, marque a caixa de seleção ao lado de NumberGuessWorkflowActivities e clique em OK.

  5. Clique com o botão direito do mouse em Workflow1.xaml no Gerenciador de Soluções e escolha Excluir. Clique em OK para confirmar.

Para modificar o código de hospedagem do fluxo de trabalho

  1. Clique duas vezes em Program.cs ou Module1.vb no Gerenciador de Soluções para exibir o código.

    Gorjeta

    Se a janela Gerenciador de Soluções não for exibida, selecione Gerenciador de Soluções no menu Exibir .

    Como este projeto foi criado usando o modelo Aplicativo de Console de Fluxo de Trabalho, Program.cs ou Module1.vb contém o seguinte código básico de hospedagem de fluxo de trabalho.

    ' Create and cache the workflow definition.
    Dim workflow1 As Activity = New Workflow1()
    WorkflowInvoker.Invoke(workflow1)
    
    // Create and cache the workflow definition.
    Activity workflow1 = new Workflow1();
    WorkflowInvoker.Invoke(workflow1);
    

    Este código de hospedagem gerado usa WorkflowInvoker. WorkflowInvoker Fornece uma maneira simples de invocar um fluxo de trabalho como se fosse uma chamada de método e pode ser usado apenas para fluxos de trabalho que não usam persistência. WorkflowApplication Fornece um modelo mais avançado para a execução de fluxos de trabalho que inclui notificação de eventos do ciclo de vida, controle de execução, retomada de marcadores e persistência. Este exemplo usa marcadores e WorkflowApplication é usado para hospedar o fluxo de trabalho. Adicione a seguinte using instrução ou Imports na parte superior de Program.cs ou Module1.vb abaixo das instruções de uso ou Imports existentes.

    Imports NumberGuessWorkflowActivities
    Imports System.Threading
    
    using NumberGuessWorkflowActivities;
    using System.Threading;
    

    Substitua as linhas de código que usam WorkflowInvoker com o seguinte código de hospedagem básico WorkflowApplication . Este código de hospedagem de exemplo demonstra as etapas básicas para hospedar e invocar um fluxo de trabalho, mas ainda não contém a funcionalidade para executar com êxito o fluxo de trabalho a partir deste tópico. Nas etapas a seguir, esse código básico é modificado e recursos adicionais são adicionados até que o aplicativo seja concluído.

    Nota

    Nestes exemplos, você deve substituir Workflow1 por , SequentialNumberGuessWorkflowou StateMachineNumberGuessWorkflow, dependendo do fluxo de trabalho concluído na etapa anterior Como: Criar um fluxo de trabalho.FlowchartNumberGuessWorkflow Se você não substituir Workflow1 , receberá erros de compilação quando tentar compilar ou executar o fluxo de trabalho.

    AutoResetEvent syncEvent = new AutoResetEvent(false);
    
    WorkflowApplication wfApp =
        new WorkflowApplication(_wf);
    
    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();
    
    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()
    

    Esse código cria um WorkflowApplication, assina três eventos do ciclo de vida do fluxo de trabalho, inicia o fluxo de trabalho com uma chamada para Rune aguarda a conclusão do fluxo de trabalho. Quando o fluxo de trabalho é concluído, o AutoResetEvent é definido e o aplicativo host é concluído.

Para definir argumentos de entrada de um fluxo de trabalho

  1. Adicione a seguinte instrução na parte superior de Program.cs ou Module1.vb abaixo das instruções ou existentes using Imports.

  2. Substitua a linha de código que cria o novo WorkflowApplication pelo código a seguir que cria e passa um dicionário de parâmetros para o fluxo de trabalho quando ele é criado.

    Nota

    Substitua Workflow1 nestes exemplos por FlowchartNumberGuessWorkflow, SequentialNumberGuessWorkflowou StateMachineNumberGuessWorkflow, dependendo do fluxo de trabalho concluído na etapa anterior Como: Criar um fluxo de trabalho . Se você não substituir Workflow1 , receberá erros de compilação quando tentar compilar ou executar o fluxo de trabalho.

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

    Este dicionário contém um elemento com uma chave de MaxNumber. As chaves no dicionário de entrada correspondem a argumentos de entrada na atividade raiz do fluxo de trabalho. MaxNumber é usado pelo fluxo de trabalho para determinar o limite superior para o número gerado aleatoriamente.

Para recuperar argumentos de saída de um fluxo de trabalho

  1. Modifique o Completed manipulador para recuperar e exibir o número de voltas usadas pelo fluxo de trabalho.

    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.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
    

Para retomar um marcador

  1. Adicione o seguinte código na parte superior do Main método logo após a declaração existente AutoResetEvent .

    AutoResetEvent idleEvent = new AutoResetEvent(false);
    
    Dim idleEvent As New AutoResetEvent(False)
    
  2. Adicione o seguinte Idle manipulador logo abaixo dos três manipuladores de ciclo de vida do fluxo de trabalho existentes no Main.

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

    Cada vez que o fluxo de trabalho fica ocioso aguardando a próxima suposição, esse manipulador é chamado e o idleAction AutoResetEvent é definido. O código na etapa a seguir usa idleEvent e syncEvent para determinar se o fluxo de trabalho está aguardando a próxima suposição ou está concluído.

    Nota

    Neste exemplo, o aplicativo host usa eventos de redefinição automática nos Completed manipuladores e Idle para sincronizar o aplicativo host com o progresso do fluxo de trabalho. Não é necessário bloquear e aguardar que o fluxo de trabalho fique ocioso antes de retomar um marcador, mas neste exemplo os eventos de sincronização são necessários para que o host saiba se o fluxo de trabalho está completo ou se está aguardando mais entrada do usuário usando o Bookmark. Para obter mais informações, consulte Favoritos.

  3. Remova a chamada para WaitOne, e substitua-a por código para coletar a entrada do usuário e retomar o Bookmark.

    Remova a seguinte linha de código.

    syncEvent.WaitOne();
    
    syncEvent.WaitOne()
    

    Substitua-o pelo exemplo a seguir.

    // 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)
        {
            if (!Int32.TryParse(Console.ReadLine(), out int Guess))
            {
                Console.WriteLine("Please enter an integer.");
            }
            else
            {
                validEntry = true;
                wfApp.ResumeBookmark("EnterGuess", Guess);
            }
        }
    }
    
    ' 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
    

Para criar e executar o aplicativo

  1. Clique com o botão direito do mouse em NumberGuessWorkflowHost no Gerenciador de Soluções e selecione Definir como Projeto de Inicialização.

  2. Pressione CTRL+F5 para compilar e executar o aplicativo. Tente adivinhar o número no menor número de voltas possível.

    Para experimentar o aplicativo por um dos outros estilos de fluxo de trabalho, substitua Workflow1 o código que cria o WorkflowApplication com FlowchartNumberGuessWorkflow, SequentialNumberGuessWorkflowou StateMachineNumberGuessWorkflow, dependendo do estilo de fluxo de trabalho desejado.

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

    Para obter instruções sobre como adicionar persistência a um aplicativo de fluxo de trabalho, consulte o próximo tópico, Como criar e executar um fluxo de trabalho de longa duração.

Exemplo

O exemplo a seguir é a listagem de código completa para o Main método.

Nota

Substitua Workflow1 nestes exemplos por FlowchartNumberGuessWorkflow, SequentialNumberGuessWorkflowou StateMachineNumberGuessWorkflow, dependendo do fluxo de trabalho concluído na etapa anterior Como: Criar um fluxo de trabalho . Se você não substituir Workflow1 , receberá erros de compilação quando tentar compilar ou executar o fluxo de trabalho.

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(_wf, inputs)
    {

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

            syncEvent.Set();
        },

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

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

        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)
        {
            if (!Int32.TryParse(Console.ReadLine(), out int Guess))
            {
                Console.WriteLine("Please enter an integer.");
            }
            else
            {
                validEntry = true;
                wfApp.ResumeBookmark("EnterGuess", Guess);
            }
        }
    }
}
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

Consulte também