Excepciones de Windows Workflow Foundation

Los flujos de trabajo pueden usar la actividad TryCatch para controlar excepciones que se producen durante la ejecución de un flujo de trabajo. Se pueden controlar estas excepciones o se pueden volver a producir usando la actividad Rethrow. Las actividades de la sección Finally se ejecutan cuando la sección Try o la sección Catches se hayan completado. Los flujos de trabajo que hospeda una instancia de WorkflowApplication también pueden usar el controlador de eventos OnUnhandledException para controlar excepciones que no controle una actividad TryCatch.

Causas de excepciones

En un flujo de trabajo, las excepciones se pueden generar de las maneras siguientes:

  • Un tiempo de espera de transacciones en TransactionScope.

  • Una excepción explícita iniciada por el flujo de trabajo mediante la actividad Throw.

  • Una excepción de .NET Framework 4.6.1 generada desde una actividad.

  • Una excepción iniciada desde el código externo, como bibliotecas, componentes o servicios que se usan en el flujo de trabajo.

Controlar las excepciones

Si la actividad inicia una excepción y no está controlada, el comportamiento predeterminado es terminar la instancia de flujo de trabajo. Si un controlador OnUnhandledException personalizado está presente, puede invalidar este comportamiento predeterminado. Este controlador da al autor de host de flujo de trabajo la oportunidad de proporcionar el control adecuado, como el registro personalizado o la anulación, cancelación o finalización del flujo de trabajo. Si un flujo de trabajo produce una excepción no administrada, se invoca el controlador OnUnhandledException. Se devuelven tres posibles acciones de OnUnhandledException que determinan el resultado final del flujo de trabajo.

  • Cancel: una instancia de flujo de trabajo cancelada es una salida correcta de una ejecución de bifurcación. Puede modelar el comportamiento de cancelación (por ejemplo, con una actividad CancellationScope). Se invoca el controlador Completed cuando el proceso de cancelación se completa. Un flujo de trabajo cancelado está en estado Cancelled.

  • Terminate: una instancia de flujo de trabajo finalizada no puede reanudarse o reiniciarse. Esto desencadena el evento Completed en el que puede proporcionar una excepción como razón por la que finalizó. Se invoca el controlador Terminated cuando el proceso de finalización se completa. Un flujo de trabajo finalizado está en el estado Faulted.

  • Abort: una instancia de flujo de trabajo anulada solo se puede reanudar si se ha configurado para ser persistente. Sin persistencia, un flujo de trabajo no se puede reanudar. En el punto en que se anula un flujo de trabajo, se perderá todo el trabajo realizado (en memoria) desde el último punto de persistencia. Para un flujo de trabajo anulado, se invoca el controlador Aborted usando la excepción como motivo cuando se completa el proceso de anulación. Sin embargo, a diferencia de Cancelled y Terminated, no se invoca el controlador Completed. Un flujo de trabajo anulado está en un estado Aborted.

En el ejemplo siguiente se invoca un flujo de trabajo que produce una excepción. El flujo de trabajo no controla la excepción y se invoca el controlador de la propiedad OnUnhandledException. El objeto WorkflowApplicationUnhandledExceptionEventArgs se inspecciona para proporcionar información acerca de la excepción y se termina el flujo de trabajo.

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 {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.
    return UnhandledExceptionAction.Terminate;

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

wfApp.Run();

Administrar excepciones con la actividad TryCatch

La administración de excepciones dentro de un flujo de trabajo se realiza mediante la actividad TryCatch. La actividad TryCatch tiene una colección de Catches de las actividades de Catch que se asocian con un tipo Exception concreto. Si la excepción producida por una actividad incluida en la sección Try de una actividad TryCatch coincide con la excepción de una actividad Catch<TException> en la colección de Catches, se administrará la excepción. Si se vuelve a producir explícitamente la excepción o se produce una nueva, esta excepción se pasa a la actividad principal. El siguiente ejemplo de código muestra una actividad TryCatch que administra un objeto ApplicationException que se produce en la sección Try mediante una actividad Throw. El mensaje de la excepción se escribe en la consola mediante la actividad Catch<TException> y, a continuación, se escribe un mensaje en la consola de la sección 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."
    }
};

Se ejecutarán las actividades en la sección Finally cuando la sección Try o la sección Catches se hayan completado. La sección Try se completa correctamente si no se produce ninguna excepción de ella, y la sección Catches se completa correctamente si no se produce o se vuelve a producir ninguna excepción desde ella. Si se produce una excepción en la sección Try de TryCatch y no está controlada por Catch<TException> en la sección Catches o si se vuelve a producir desde Catches, las actividades de Finally no se ejecutarán a menos que ocurra algo de lo siguiente.

Control de excepciones contra compensación

La diferencia entre el control de excepciones y la compensación es que el primero se produce durante la ejecución de una actividad. La compensación, sin embargo, se produce después de que una actividad se haya completado correctamente. El control de excepciones proporciona una oportunidad para limpiar después de que la actividad produzca la excepción, mientras la compensación proporciona un mecanismo por el que se puede deshacer el trabajo terminado correctamente de una actividad completada previamente. Para obtener más información, vea Compensación.

Consulte también