Usando WorkflowInvoker e WorkflowApplicationUsing WorkflowInvoker and WorkflowApplication

Windows Workflow Foundation (WF) fornece vários métodos de Hospedagem de fluxos de trabalho.Windows Workflow Foundation (WF) provides several methods of hosting workflows. WorkflowInvoker fornece uma maneira simples para chamar um fluxo de trabalho como se fosse uma chamada de método e pode ser usado somente para os fluxos de trabalho que não usam persistência.WorkflowInvoker provides a simple way for invoking a workflow as if it were a method call and can be used only for workflows that do not use persistence. WorkflowApplication fornece um modelo mais rico para executar fluxos de trabalho que inclui notificação de eventos de ciclo de vida, controle de execução, de ressunção do indexador, e de persistência.WorkflowApplication provides a richer model for executing workflows that includes notification of lifecycle events, execution control, bookmark resumption, and persistence. WorkflowServiceHost fornece suporte para atividades de mensagem e é basicamente usado com serviços de fluxo de trabalho.WorkflowServiceHost provides support for messaging activities and is primarily used with workflow services. Este tópico apresenta o fluxo de trabalho que hospeda com WorkflowInvoker e WorkflowApplication.This topic introduces you to workflow hosting with WorkflowInvoker and WorkflowApplication. Para obter mais informações sobre como hospedar fluxos de trabalho com o WorkflowServiceHost , consulte serviços de fluxo de trabalho e serviços de fluxo de trabalho de hospedagem.For more information about hosting workflows with WorkflowServiceHost, see Workflow Services and Hosting Workflow Services Overview.

Usando WorkflowInvokerUsing WorkflowInvoker

WorkflowInvoker fornece um modelo para executar um fluxo de trabalho como se fosse um chamada de método.WorkflowInvoker provides a model for executing a workflow as if it were a method call. Para chamar um fluxo de trabalho usando WorkflowInvoker, chame o método de Invoke e passe a definição de fluxo de trabalho de fluxo de trabalho para chamar.To invoke a workflow using WorkflowInvoker, call the Invoke method and pass in the workflow definition of the workflow to invoke. Nesse exemplo, uma atividade de WriteLine é chamada usando WorkflowInvoker.In this example, a WriteLine activity is invoked using WorkflowInvoker.

Activity wf = new WriteLine
{
    Text = "Hello World."
};

WorkflowInvoker.Invoke(wf);

Quando um fluxo de trabalho é chamado usando WorkflowInvoker, o fluxo de trabalho é executado no segmento de chamada e os blocos de método Invoke até que o fluxo de trabalho está completo, incluindo qualquer tempo ocioso.When a workflow is invoked using WorkflowInvoker, the workflow executes on the calling thread and the Invoke method blocks until the workflow is complete, including any idle time. Para configurar um intervalo de tempo limite em que o fluxo de trabalho deveria concluir, use uma das sobrecargas de Invoke que usa um parâmetro de TimeSpan .To configure a time-out interval in which the workflow must complete, use one of the Invoke overloads that takes a TimeSpan parameter. Nesse exemplo, um fluxo de trabalho é chamado duas vezes em com dois intervalos de tempo limite diferentes.In this example, a workflow is invoked twice with two different time-out intervals. Os primeiros complets de fluxo de trabalho, mas os segundos não.The first workflow complets, but the second does not.

Activity wf = new Sequence()
{
    Activities =
    {
        new WriteLine()
        {
            Text = "Before the 1 minute delay."
        },
        new Delay()
        {
            Duration = TimeSpan.FromMinutes(1)
        },
        new WriteLine()
        {
            Text = "After the 1 minute delay."
        }
    }
};

// This workflow completes successfully.
WorkflowInvoker.Invoke(wf, TimeSpan.FromMinutes(2));

// This workflow does not complete and a TimeoutException
// is thrown.
try
{
    WorkflowInvoker.Invoke(wf, TimeSpan.FromSeconds(30));
}
catch (TimeoutException ex)
{
    Console.WriteLine(ex.Message);
}

Observação

TimeoutException é acionada somente se o intervalo de tempo limite decorre e fluxo de trabalho se torna ocioso durante a execução.The TimeoutException is only thrown if the time-out interval elapses and the workflow becomes idle during execution. Um fluxo de trabalho que recebe mais tempo do intervalo de tempo limite especificado para concluir concluída com êxito se o fluxo de trabalho não se torna ocioso.A workflow that takes longer than the specified time-out interval to complete completes successfully if the workflow does not become idle.

WorkflowInvoker também fornece versões assíncronas do método invoke.WorkflowInvoker also provides asynchronous versions of the invoke method. Para obter mais informações, consulte InvokeAsync e BeginInvoke.For more information, see InvokeAsync and BeginInvoke.

Argumentos de entrada de configuração de um fluxo de trabalhoSetting Input Arguments of a Workflow

Os dados podem ser passados em um fluxo de trabalho usando um dicionário de parâmetros de entrada, fechado pelo nome de argumento, que mapeiam para argumentos de entrada de fluxo de trabalho.Data can be passed into a workflow using a dictionary of input parameters, keyed by argument name, that map to the input arguments of the workflow. Nesse exemplo, WriteLine é chamado e o valor para o argumento de Text é especificado usando o dicionário de parâmetros.In this example, a WriteLine is invoked and the value for its Text argument is specified using the dictionary of input parameters.

Activity wf = new WriteLine();

Dictionary<string, object> inputs = new Dictionary<string, object>();
inputs.Add("Text", "Hello World.");

WorkflowInvoker.Invoke(wf, inputs);

Recuperando argumentos de saída de um fluxo de trabalhoRetrieving Output Arguments of a Workflow

Parâmetros de saída de um fluxo de trabalho podem ser obtidos usando o dicionário de saída que é retornado da chamada a Invoke.The output parameters of a workflow can be obtained using the outputs dictionary that is returned from the call to Invoke. O exemplo a seguir chama um fluxo de trabalho que consiste em uma única atividade de Divide que tem dois argumentos conectados e dois argumentos de saída.The following example invokes a workflow consisting of a single Divide activity that has two input arguments and two output arguments. Quando o fluxo de trabalho é chamado, o dicionário de arguments é passado que contém os valores para cada argumento de entrada, fechado pelo nome do argumento.When the workflow is invoked, the arguments dictionary is passed which contains the values for each input argument, keyed by argument name. Quando o Invoke a chamada retorna, cada argumento de saída é retornado no dicionário de outputs , também fechado pelo nome do argumento.When the call to Invoke returns, each output argument is returned in the outputs dictionary, also keyed by argument name.

public sealed class Divide : CodeActivity
{
    [RequiredArgument]
    public InArgument<int> Dividend { get; set; }

    [RequiredArgument]
    public InArgument<int> Divisor { get; set; }

    public OutArgument<int> Remainder { get; set; }
    public OutArgument<int> Result { get; set; }

    protected override void Execute(CodeActivityContext context)
    {
        int quotient = Dividend.Get(context) / Divisor.Get(context);
        int remainder = Dividend.Get(context) % Divisor.Get(context);

        Result.Set(context, quotient);
        Remainder.Set(context, remainder);
    }
}
int dividend = 500;
int divisor = 36;

Dictionary<string, object> arguments = new Dictionary<string, object>();
arguments.Add("Dividend", dividend);
arguments.Add("Divisor", divisor);

IDictionary<string, object> outputs =
    WorkflowInvoker.Invoke(new Divide(), arguments);

Console.WriteLine("{0} / {1} = {2} Remainder {3}",
    dividend, divisor, outputs["Result"], outputs["Remainder"]);

Se o fluxo de trabalho deriva de ActivityWithResult, como CodeActivity<TResult> ou Activity<TResult>, e há argumentos de saída além do argumento bem definido de saída de Result , uma sobrecarga não genérico de Invoke deve ser usada para recuperar os argumentos adicionais.If the workflow derives from ActivityWithResult, such as CodeActivity<TResult> or Activity<TResult>, and there are output arguments in addition to the well-defined Result output argument, a non-generic overload of Invoke must be used in order to retrieve the additional arguments. Para fazer isso, a definição de fluxo de trabalho passada em Invoke deve ser do tipo Activity.To do this, the workflow definition passed into Invoke must be of type Activity. Nesse exemplo a atividade de Divide deriva de CodeActivity<int>, mas é declarada como Activity de modo que uma sobrecarga não genérico de Invoke é usada que retorna um dicionário dos argumentos em vez de um único valor de retorno.In this example the Divide activity derives from CodeActivity<int>, but is declared as Activity so that a non-generic overload of Invoke is used which returns a dictionary of arguments instead of a single return value.

public sealed class Divide : CodeActivity<int>
{
    public InArgument<int> Dividend { get; set; }
    public InArgument<int> Divisor { get; set; }
    public OutArgument<int> Remainder { get; set; }

    protected override int Execute(CodeActivityContext context)
    {
        int quotient = Dividend.Get(context) / Divisor.Get(context);
        int remainder = Dividend.Get(context) % Divisor.Get(context);

        Remainder.Set(context, remainder);

        return quotient;
    }
}
int dividend = 500;
int divisor = 36;

Dictionary<string, object> arguments = new Dictionary<string, object>();
arguments.Add("Dividend", dividend);
arguments.Add("Divisor", divisor);

Activity wf = new Divide();

IDictionary<string, object> outputs =
    WorkflowInvoker.Invoke(wf, arguments);

Console.WriteLine("{0} / {1} = {2} Remainder {3}",
    dividend, divisor, outputs["Result"], outputs["Remainder"]);

Usando WorkflowApplicationUsing WorkflowApplication

WorkflowApplication fornece um conjunto rico de recursos para gerenciamento de instância de fluxo de trabalho.WorkflowApplication provides a rich set of features for workflow instance management. WorkflowApplication atua como um proxy segura do que a WorkflowInstancereal, que encapsula o runtime, e fornece métodos para criar e carregar instâncias de fluxo de trabalho, pausar e continuar-las, finalizar, e notificação de eventos de ciclo de vida.WorkflowApplication acts as a thread safe proxy to the actual WorkflowInstance, which encapsulates the runtime, and provides methods for creating and loading workflow instances, pausing and resuming, terminating, and notification of lifecycle events. Para executar um fluxo de trabalho usando WorkflowApplication que você cria WorkflowApplication, assinar os eventos desejados do ciclo de vida, a inicia o fluxo de trabalho, e espera-o em concluir.To run a workflow using WorkflowApplication you create the WorkflowApplication, subscribe to any desired lifecycle events, start the workflow, and then wait for it to finish. Nesse exemplo, uma definição de fluxo de trabalho que consiste em uma atividade de WriteLine é criada e WorkflowApplication são criados usando a definição especificada de fluxo de trabalho.In this example, a workflow definition that consists of a WriteLine activity is created and a WorkflowApplication is created using the specified workflow definition. Completed é tratado para que o host é notificado quando o fluxo de trabalho for concluída, o fluxo de trabalho é iniciado com uma chamada a Run, e então o host espera o fluxo de trabalho para concluir.Completed is handled so the host is notified when the workflow completes, the workflow is started with a call to Run, and then the host waits for the workflow to complete. Quando o fluxo de trabalho terminar, AutoResetEvent é ajustado e o aplicativo host pode continuar a execução, conforme mostrado no exemplo o seguir.When the workflow completes, the AutoResetEvent is set and the host application can resume execution, as shown in the following example.

AutoResetEvent syncEvent = new AutoResetEvent(false);

Activity wf = new WriteLine
{
    Text = "Hello World."
};

// Create the WorkflowApplication using the desired
// workflow definition.
WorkflowApplication wfApp = new WorkflowApplication(wf);

// Handle the desired lifecycle events.
wfApp.Completed = delegate(WorkflowApplicationCompletedEventArgs e)
{
    syncEvent.Set();
};

// Start the workflow.
wfApp.Run();

// Wait for Completed to arrive and signal that
// the workflow is complete.
syncEvent.WaitOne();

Eventos de ciclo de vida de WorkflowApplicationWorkflowApplication Lifecycle Events

Além de Completed, os autores de host podem ser notificados quando um fluxo de trabalho é descarregado (Unloaded), anuladas (Aborted), se torna ocioso (Idle e PersistableIdle), ou uma exceção não manipulada ocorre (OnUnhandledException).In addition to Completed, host authors can be notified when a workflow is unloaded (Unloaded), aborted (Aborted), becomes idle (Idle and PersistableIdle), or an unhandled exception occurs (OnUnhandledException). Os desenvolvedores de aplicativos de fluxo de trabalho podem tratar essas notificações e a ação apropriada, conforme mostrado no exemplo o seguir.Workflow application developers can handle these notifications and take appropriate action, as shown in the following example.

wfApp.Completed = delegate(WorkflowApplicationCompletedEventArgs e)
{
    if (e.CompletionState == ActivityInstanceState.Faulted)
    {
        Console.WriteLine("Workflow {0} Terminated.", e.InstanceId);
        Console.WriteLine("Exception: {0}\n{1}",
            e.TerminationException.GetType().FullName,
            e.TerminationException.Message);
    }
    else if (e.CompletionState == ActivityInstanceState.Canceled)
    {
        Console.WriteLine("Workflow {0} Canceled.", e.InstanceId);
    }
    else
    {
        Console.WriteLine("Workflow {0} Completed.", e.InstanceId);

        // Outputs can be retrieved from the Outputs dictionary,
        // keyed by argument name.
        // Console.WriteLine("The winner is {0}.", e.Outputs["Winner"]);
    }
};

wfApp.Aborted = delegate(WorkflowApplicationAbortedEventArgs e)
{
    // Display the exception that caused the workflow
    // to abort.
    Console.WriteLine("Workflow {0} Aborted.", e.InstanceId);
    Console.WriteLine("Exception: {0}\n{1}",
        e.Reason.GetType().FullName,
        e.Reason.Message);
};

wfApp.Idle = delegate(WorkflowApplicationIdleEventArgs e)
{
    // Perform any processing that should occur
    // when a workflow goes idle. If the workflow can persist,
    // both Idle and PersistableIdle are called in that order.
    Console.WriteLine("Workflow {0} Idle.", e.InstanceId);
};

wfApp.PersistableIdle = delegate(WorkflowApplicationIdleEventArgs e)
{
    // Instruct the runtime to persist and unload the workflow.
    // Choices are None, Persist, and Unload.
    return PersistableIdleAction.Unload;
};

wfApp.Unloaded = delegate(WorkflowApplicationEventArgs e)
{
    Console.WriteLine("Workflow {0} Unloaded.", e.InstanceId);
};

wfApp.OnUnhandledException = delegate(WorkflowApplicationUnhandledExceptionEventArgs e)
{
    // Display the unhandled exception.
    Console.WriteLine("OnUnhandledException in Workflow {0}\n{1}",
        e.InstanceId, e.UnhandledException.Message);

    Console.WriteLine("ExceptionSource: {0} - {1}",
        e.ExceptionSource.DisplayName, e.ExceptionSourceInstanceId);

    // Instruct the runtime to terminate the workflow.
    // Other choices are Abort and Cancel. Terminate
    // is the default if no OnUnhandledException handler
    // is present.
    return UnhandledExceptionAction.Terminate;
};

Argumentos de entrada de configuração de um fluxo de trabalhoSetting Input Arguments of a Workflow

Os dados podem ser passados em um fluxo de trabalho como são iniciados usar um dicionário de parâmetros, semelhante à forma que os dados são passados na o usar WorkflowInvoker.Data can be passed into a workflow as it is started using a dictionary of parameters, similar to the way data is passed in when using WorkflowInvoker. Cada item em mapas de dicionário para um argumento de entrada de fluxo de trabalho especificado.Each item in the dictionary maps to an input argument of the specified workflow. Nesse exemplo, um fluxo de trabalho que consiste em uma atividade de WriteLine é chamado e o argumento de Text são especificados usando o dicionário de parâmetros.In this example, a workflow that consists of a WriteLine activity is invoked and its Text argument is specified using the dictionary of input parameters.

AutoResetEvent syncEvent = new AutoResetEvent(false);

Activity wf = new WriteLine();

// Create the dictionary of input parameters.
Dictionary<string, object> inputs = new Dictionary<string, object>();
inputs.Add("Text", "Hello World!");

// Create the WorkflowApplication using the desired
// workflow definition and dictionary of input parameters.
WorkflowApplication wfApp = new WorkflowApplication(wf, inputs);

// Handle the desired lifecycle events.
wfApp.Completed = delegate(WorkflowApplicationCompletedEventArgs e)
{
    syncEvent.Set();
};

// Start the workflow.
wfApp.Run();

// Wait for Completed to arrive and signal that
// the workflow is complete.
syncEvent.WaitOne();

Recuperando argumentos de saída de um fluxo de trabalhoRetrieving Output Arguments of a Workflow

Quando um fluxo de trabalho concluir, os argumentos de saída podem ser recuperados no manipulador de Completed acessando o dicionário de WorkflowApplicationCompletedEventArgs.Outputs .When a workflow completes, any output arguments can be retrieved in the Completed handler by accessing the WorkflowApplicationCompletedEventArgs.Outputs dictionary. O exemplo a seguir hospeda um fluxo de trabalho usando WorkflowApplication.The following example hosts a workflow using WorkflowApplication. Uma WorkflowApplication instância é construída usando uma definição de fluxo de trabalho que consiste em uma única DiceRoll atividade.A WorkflowApplication instance is constructed using a workflow definition consisting of a single DiceRoll activity. A atividade de DiceRoll tem dois argumentos de saída que representam os resultados da operação de rolagem de dados.The DiceRoll activity has two output arguments that represent the results of the dice roll operation. Quando o fluxo de trabalho for concluído, a saída são recuperadas no manipulador de Completed .When the workflow completes, the outputs are retrieved in the Completed handler.

public sealed class DiceRoll : CodeActivity
{
    public OutArgument<int> D1 { get; set; }
    public OutArgument<int> D2 { get; set; }

    static Random r = new Random();

    protected override void Execute(CodeActivityContext context)
    {
        D1.Set(context, r.Next(1, 7));
        D2.Set(context, r.Next(1, 7));
    }
}
 // Create a WorkflowApplication instance.
 WorkflowApplication wfApp = new WorkflowApplication(new DiceRoll());

 // Subscribe to any desired workflow lifecycle events.
 wfApp.Completed = delegate(WorkflowApplicationCompletedEventArgs e)
 {
     if (e.CompletionState == ActivityInstanceState.Faulted)
     {
         Console.WriteLine("Workflow {0} Terminated.", e.InstanceId);
         Console.WriteLine("Exception: {0}\n{1}",
             e.TerminationException.GetType().FullName,
             e.TerminationException.Message);
     }
     else if (e.CompletionState == ActivityInstanceState.Canceled)
     {
         Console.WriteLine("Workflow {0} Canceled.", e.InstanceId);
     }
     else
     {
         Console.WriteLine("Workflow {0} Completed.", e.InstanceId);

         // Outputs can be retrieved from the Outputs dictionary,
         // keyed by argument name.
         Console.WriteLine("The two dice are {0} and {1}.",
             e.Outputs["D1"], e.Outputs["D2"]);
     }
 };

// Run the workflow.
 wfApp.Run();

Observação

WorkflowApplication e WorkflowInvoker têm um dicionário de argumentos de entrada e retornam um dicionário de argumentos de out .WorkflowApplication and WorkflowInvoker take a dictionary of input arguments and return a dictionary of out arguments. Esses parâmetros, propriedades, e valores de retorno do dicionário são do tipo IDictionary<string, object>.These dictionary parameters, properties, and return values are of type IDictionary<string, object>. A instância real da classe dicionário que é passada em pode ser qualquer classe que implemente IDictionary<string, object>.The actual instance of the dictionary class that is passed in can be any class that implements IDictionary<string, object>. Nesses exemplos, Dictionary<string, object> é usado.In these examples, Dictionary<string, object> is used. Para obter mais informações sobre dicionários, consulte IDictionary<TKey,TValue> e Dictionary<TKey,TValue> .For more information about dictionaries, see IDictionary<TKey,TValue> and Dictionary<TKey,TValue>.

Passando dados em um fluxo de trabalho em execução usando indicadoresPassing Data into a Running Workflow Using Bookmarks

Indexadores são o mecanismo por que uma atividade passiva pode esperar para ser continuado e é um mecanismo para passar dados em uma instância em execução de fluxo de trabalho.Bookmarks are the mechanism by which an activity can passively wait to be resumed and are a mechanism for passing data into a running workflow instance. Se uma atividade está aguardando dados, Bookmark pode criar e registrar um método callback a ser chamado quando Bookmark é que, conforme mostrado no exemplo o seguir.If an activity is waiting for data, it can create a Bookmark and register a callback method to be called when the Bookmark is resumed, as shown in the following example.

public sealed class ReadLine : NativeActivity<string>
{
    [RequiredArgument]
    public InArgument<string> BookmarkName { get; set; }

    protected override void Execute(NativeActivityContext context)
    {
        // Create a Bookmark and wait for it to be resumed.
        context.CreateBookmark(BookmarkName.Get(context),
            new BookmarkCallback(OnResumeBookmark));
    }

    // NativeActivity derived activities that do asynchronous operations by calling
    // one of the CreateBookmark overloads defined on System.Activities.NativeActivityContext
    // must override the CanInduceIdle property and return true.
    protected override bool CanInduceIdle
    {
        get { return true; }
    }

    public void OnResumeBookmark(NativeActivityContext context, Bookmark bookmark, object obj)
    {
        // When the Bookmark is resumed, assign its value to
        // the Result argument.
        Result.Set(context, (string)obj);
    }

Quando executada, a atividade de ReadLine cria Bookmark, registra um retorno de chamada, e espera em Bookmark a ser continuado.When executed, the ReadLine activity creates a Bookmark, registers a callback, and then waits for the Bookmark to be resumed. Quando é continuada, a atividade de ReadLine atribui os dados que foram passados com Bookmark ao seu argumento de Result .When it is resumed, the ReadLine activity assigns the data that was passed with the Bookmark to its Result argument. Nesse exemplo, um fluxo de trabalho é criado que usa a atividade de ReadLine para coletar o nome de usuário e para o exibir a janela do console.In this example, a workflow is created that uses the ReadLine activity to gather the user’s name and display it to the console window.

Variable<string> name = new Variable<string>();

Activity wf = new Sequence
{
    Variables = { name },
    Activities =
     {
         new WriteLine
         {
             Text = "What is your name?"
         },
         new ReadLine
         {
             BookmarkName = "UserName",
             Result = new OutArgument<string>(name)
         },
         new WriteLine
         {
             Text = new InArgument<string>((env) =>
                 ("Hello, " + name.Get(env)))
         }
     }
};

// Create a WorkflowApplication instance.
WorkflowApplication wfApp = new WorkflowApplication(wf);

// Workflow lifecycle events omitted except idle.
AutoResetEvent idleEvent = new AutoResetEvent(false);

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

// Run the workflow.
wfApp.Run();

// Wait for the workflow to go idle before gathering
// the user's input.
idleEvent.WaitOne();

// Gather the user's input and resume the bookmark.
// Bookmark resumption only occurs when the workflow
// is idle. If a call to ResumeBookmark is made and the workflow
// is not idle, ResumeBookmark blocks until the workflow becomes
// idle before resuming the bookmark.
BookmarkResumptionResult result = wfApp.ResumeBookmark("UserName",
    Console.ReadLine());

// Possible BookmarkResumptionResult values:
// Success, NotFound, or NotReady
Console.WriteLine("BookmarkResumptionResult: {0}", result);

Quando a atividade de ReadLine é executada, cria Bookmark chamado UserName e espera no indexador a ser continuado.When the ReadLine activity is executed, it creates a Bookmark named UserName and then waits for the bookmark to be resumed. O host reúne os dados desejados e depois Bookmark.The host collects the desired data and then resumes the Bookmark. Retoma de fluxo de trabalho, exibe o nome, e então usa.The workflow resumes, displays the name, and then completes.

O aplicativo host pode inspecionar o fluxo de trabalho para determinar se houver qualquer marcador ativo.The host application can inspect the workflow to determine if there are any active bookmarks. Pode fazer isso chamando o método de GetBookmarks de uma instância de WorkflowApplication , ou inspecionando WorkflowApplicationIdleEventArgs no manipulador de Idle .It can do this by calling the GetBookmarks method of a WorkflowApplication instance, or by inspecting the WorkflowApplicationIdleEventArgs in the Idle handler.

O exemplo de código é como o exemplo anterior exceto que os indicadores ativas são enumerados antes que o indexador é continuado.The following code example is like the previous example except that the active bookmarks are enumerated before the bookmark is resumed. O fluxo de trabalho é iniciado, e depois que Bookmark é criado e fluxo de trabalho aparece ociosa, GetBookmarks é chamado.The workflow is started, and once the Bookmark is created and the workflow goes idle, GetBookmarks is called. Quando o fluxo de trabalho for concluído, a saída a seguir são exibidas no console.When the workflow is completed, the following output is displayed to the console.

Que é o nome?What is your name?
BookmarkName: username-OwnerDisplayName: ReadLine Steve Olá, SteveBookmarkName: UserName - OwnerDisplayName: ReadLine Steve Hello, Steve

Variable<string> name = new Variable<string>();

Activity wf = new Sequence
{
    Variables = { name },
    Activities =
     {
         new WriteLine
         {
             Text = "What is your name?"
         },
         new ReadLine
         {
             BookmarkName = "UserName",
             Result = new OutArgument<string>(name)
         },
         new WriteLine
         {
             Text = new InArgument<string>((env) =>
                 ("Hello, " + name.Get(env)))
         }
     }
};

// Create a WorkflowApplication instance.
WorkflowApplication wfApp = new WorkflowApplication(wf);

// Workflow lifecycle events omitted except idle.
AutoResetEvent idleEvent = new AutoResetEvent(false);

wfApp.Idle = delegate(WorkflowApplicationIdleEventArgs e)
{
    // You can also inspect the bookmarks from the Idle handler
    // using e.Bookmarks

    idleEvent.Set();
};

// Run the workflow.
wfApp.Run();

// Wait for the workflow to go idle and give it a chance
// to create the Bookmark.
idleEvent.WaitOne();

// Inspect the bookmarks
foreach (BookmarkInfo info in wfApp.GetBookmarks())
{
    Console.WriteLine("BookmarkName: {0} - OwnerDisplayName: {1}",
        info.BookmarkName, info.OwnerDisplayName);
}

// Gather the user's input and resume the bookmark.
wfApp.ResumeBookmark("UserName", Console.ReadLine());

O exemplo de código inspeciona WorkflowApplicationIdleEventArgs passado para o manipulador de Idle de uma instância de WorkflowApplication .The following code example inspects the WorkflowApplicationIdleEventArgs passed into the Idle handler of a WorkflowApplication instance. Nesse exemplo a ociosa indo de fluxo de trabalho tem um Bookmark com um nome de EnterGuess, possuídas por uma atividade chamada ReadInt.In this example the workflow going idle has one Bookmark with a name of EnterGuess, owned by an activity named ReadInt. Este exemplo de código se baseia em como: executar um fluxo de trabalho, que faz parte do tutorial de introdução.This code example is based off of How to: Run a Workflow, which is part of the Getting Started Tutorial. Se o manipulador de Idle nessa etapa é alterado para conter o código deste exemplo, a seguinte saída são exibidas.If the Idle handler in that step is modified to contain the code from this example, the following output is displayed.

BookmarkName: EnterGuess - OwnerDisplayName: ReadIntBookmarkName: EnterGuess - OwnerDisplayName: ReadInt

wfApp.Idle = delegate(WorkflowApplicationIdleEventArgs e)
{
    foreach (BookmarkInfo info in e.Bookmarks)
    {
        Console.WriteLine("BookmarkName: {0} - OwnerDisplayName: {1}",
            info.BookmarkName, info.OwnerDisplayName);
    }

    idleEvent.Set();
};

ResumoSummary

WorkflowInvoker fornece uma maneira leve de invocar fluxos de trabalho e, embora fornece métodos para passar dados no início de um fluxo de trabalho e extrair dados de um fluxo de trabalho concluído, não fornece cenários mais complexos que é onde WorkflowApplication pode ser usado.WorkflowInvoker provides a lightweight way to invoke workflows, and although it provides methods for passing data in at the start of a workflow and extracting data from a completed workflow, it does not provide for more complex scenarios which is where WorkflowApplication can be used.