Partilhar via


Exceções do Windows Workflow Foundation

Os fluxos de trabalho podem usar a atividade TryCatch para lidar com exceções geradas durante a execução de um fluxo de trabalho. Essas exceções podem ser tratadas ou relançadas usando a atividade Rethrow. As atividades na seção Finally são executadas quando a seção Try ou a seção Catches é concluída. Os fluxos de trabalho hospedados por uma instância WorkflowApplication também podem usar o manipulador de eventos OnUnhandledException para lidar com exceções que não são manipuladas por uma atividade TryCatch.

Causas das exceções

Em um fluxo de trabalho, as exceções podem ser geradas das seguintes maneiras:

  • Um tempo limite de transações em TransactionScope.

  • Uma exceção explícita lançada pelo fluxo de trabalho usando a atividade Throw.

  • Uma exceção do .NET Framework 4.6.1 lançada de uma atividade.

  • Uma exceção lançada a partir de código externo, como bibliotecas, componentes ou serviços que são usados no fluxo de trabalho.

Tratamento de exceções

Se uma exceção for lançada por uma atividade e não for tratada, o comportamento padrão será encerrar a instância do fluxo de trabalho. Se um manipulador de OnUnhandledException personalizado estiver presente, ele poderá substituir esse comportamento padrão. Esse manipulador dá ao autor do host do fluxo de trabalho a oportunidade de fornecer o tratamento apropriado, como registro em log personalizado, cancelamento do fluxo de trabalho, cancelamento do fluxo de trabalho ou encerramento do fluxo de trabalho. Se um fluxo de trabalho gerar uma exceção que não é tratada, o manipulador de OnUnhandledException é invocado. Há três ações possíveis retornadas de OnUnhandledException que determinam o resultado final do fluxo de trabalho.

  • Cancelar - Uma instância de fluxo de trabalho cancelada é uma saída normal de uma execução de ramificação. Você pode modelar o comportamento de cancelamento (por exemplo, usando uma atividade CancellationScope). O manipulador Completed é invocado quando o processo de cancelamento é concluído. Um fluxo de trabalho cancelado está no estado Cancelado.

  • Encerrar - Uma instância de fluxo de trabalho encerrada não pode ser retomada ou reiniciada. Isso aciona o evento Completed no qual você pode fornecer uma exceção como o motivo pelo qual ele foi encerrado. O manipulador Terminated é invocado quando o processo de encerramento é concluído. Um fluxo de trabalho encerrado está no estado com defeito.

  • Abortar - Uma instância de fluxo de trabalho abortada só pode ser retomada se tiver sido configurada para ser persistente. Sem persistência, um fluxo de trabalho não pode ser retomado. No ponto em que um fluxo de trabalho é abortado, qualquer trabalho realizado (na memória) desde o último ponto de persistência será perdido. Para um fluxo de trabalho abortado, o manipulador Aborted é invocado usando a exceção como o motivo quando o processo de anulação é concluído. No entanto, ao contrário de Cancelled e Terminated, o manipulador Completed não é invocado. Um fluxo de trabalho abortado está em um estado Abortado.

O exemplo a seguir invoca um fluxo de trabalho que gera uma exceção. A exceção não é tratada pelo fluxo de trabalho e o manipulador de OnUnhandledException é invocado. Os WorkflowApplicationUnhandledExceptionEventArgs são inspecionados para fornecer informações sobre a exceção e o fluxo de trabalho é encerrado.

Activity wf = new Sequence
{
    Activities =
     {
         new WriteLine
         {
             Text = "Starting the workflow."
         },
         new Throw
        {
            Exception = new InArgument<Exception>((env) =>
                new ApplicationException("Something unexpected happened."))
        },
        new WriteLine
         {
             Text = "Ending the workflow."
         }
     }
};

WorkflowApplication wfApp = new WorkflowApplication(wf);

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

    Console.WriteLine($"ExceptionSource: {e.ExceptionSource.DisplayName} - {e.ExceptionSourceInstanceId}");

    // Instruct the runtime to terminate the workflow.
    return UnhandledExceptionAction.Terminate;

    // Other choices are UnhandledExceptionAction.Abort and
    // UnhandledExceptionAction.Cancel
};

wfApp.Run();

Manipulando exceções com a atividade TryCatch

A manipulação de exceções dentro de um fluxo de trabalho é realizada com a atividade TryCatch. A atividade TryCatch tem uma coleção Catches de atividades Catch cada uma associada a um tipo de Exception específico. Se a exceção lançada por uma atividade contida na seção Try de uma atividade de TryCatch corresponder à exceção de uma atividade Catch<TException> na coleção Catches, a exceção será tratada. Se a exceção for explicitamente relançada ou uma nova exceção for lançada, essa exceção passará para a atividade pai. O exemplo de código a seguir mostra uma atividade TryCatch que manipula um ApplicationException que é lançado na seção Try por uma atividade Throw. A mensagem da exceção é gravada no console pela atividade Catch<TException> e, em seguida, uma mensagem é gravada no console na seção Finally.

DelegateInArgument<ApplicationException> ex = new DelegateInArgument<ApplicationException>()
{
    Name = "ex"
};

Activity wf = new TryCatch
{
    Try = new Throw()
    {
        Exception = new InArgument<Exception>((env) => new ApplicationException("An ApplicationException was thrown."))
    },
    Catches =
    {
        new Catch<ApplicationException>
        {
            Action = new ActivityAction<ApplicationException>
            {
                Argument = ex,
                Handler = new WriteLine()
                {
                    Text = new InArgument<string>((env) => ex.Get(env).Message)
                }
            }
        }
    },
    Finally = new WriteLine()
    {
        Text = "Executing in Finally."
    }
};

As atividades na seção Finally são executadas quando a seção Try ou a seção Catches é concluída com êxito. A seção Try é concluída com êxito se nenhuma exceção for lançada a partir dela, e a seção Catches é concluída com êxito se nenhuma exceção for lançada ou relançada a partir dela. Se uma exceção for lançada na seção Try de um TryCatch e não for tratada por um Catch<TException> na seção Catches, ou for relançada do Catches, as atividades no Finally não serão executadas, a menos que ocorra uma das seguintes situações.

Tratamento de exceções versus compensação

A diferença entre o tratamento de exceções e a compensação é que o tratamento de exceções ocorre durante a execução de uma atividade. A compensação ocorre após a conclusão bem-sucedida de uma atividade. O tratamento de exceções oferece uma oportunidade de limpeza depois que a atividade gera a exceção, enquanto a compensação fornece um mecanismo pelo qual o trabalho concluído com êxito de uma atividade concluída anteriormente pode ser desfeito. Para obter mais informações, consulte Compensation.

Ver também