Nota
O acesso a esta página requer autorização. Pode tentar iniciar sessão ou alterar os diretórios.
O acesso a esta página requer autorização. Pode tentar alterar os diretórios.
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
Abra a solução do tópico anterior Como: Criar uma atividade usando o Visual Studio 2012.
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 .
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
NumberGuessWorkflowHostna 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.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.
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
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
usinginstruçã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.Threadingusing 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
Workflow1por ,SequentialNumberGuessWorkflowouStateMachineNumberGuessWorkflow, dependendo do fluxo de trabalho concluído na etapa anterior Como: Criar um fluxo de trabalho.FlowchartNumberGuessWorkflowSe você não substituirWorkflow1, 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
Adicione a seguinte instrução na parte superior de Program.cs ou Module1.vb abaixo das instruções ou existentes
usingImports.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
Workflow1nestes exemplos porFlowchartNumberGuessWorkflow,SequentialNumberGuessWorkflowouStateMachineNumberGuessWorkflow, dependendo do fluxo de trabalho concluído na etapa anterior Como: Criar um fluxo de trabalho . Se você não substituirWorkflow1, 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
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
Adicione o seguinte código na parte superior do
Mainmétodo logo após a declaração existente AutoResetEvent .AutoResetEvent idleEvent = new AutoResetEvent(false);Dim idleEvent As New AutoResetEvent(False)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 SubCada vez que o fluxo de trabalho fica ocioso aguardando a próxima suposição, esse manipulador é chamado e o
idleActionAutoResetEvent é definido. O código na etapa a seguir usaidleEventesyncEventpara 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.
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
Clique com o botão direito do mouse em NumberGuessWorkflowHost no Gerenciador de Soluções e selecione Definir como Projeto de Inicialização.
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
Workflow1o código que cria o WorkflowApplication comFlowchartNumberGuessWorkflow,SequentialNumberGuessWorkflowouStateMachineNumberGuessWorkflow, 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