Windows Workflow Foundation 异常

工作流可以使用 TryCatch 活动来处理在工作流执行期间引发的异常。 可以处理这些异常,也可以使用 Rethrow 活动重新引发这些异常。 当 Try 节或 Catches 节完成时,将执行 Finally 节中的活动。 由 WorkflowApplication 实例托管的工作流还可以使用 OnUnhandledException 事件处理程序来处理 TryCatch 活动未处理的异常。

异常原因

在工作流中,可以通过以下方式生成异常:

  • TransactionScope中的事务超时。

  • 工作流使用 Throw 活动引发的显式异常。

  • 从活动引发的 .NET Framework 4.6.1 异常。

  • 从外部代码(如工作流中使用的库、组件或服务)引发的异常。

处理异常

如果活动引发异常且未经处理,则默认行为是终止工作流实例。 如果存在自定义 OnUnhandledException 处理程序,则可以替代此默认行为。 此处理程序使工作流主机作者有机会提供适当的处理,例如自定义日志记录、中止工作流、取消工作流或终止工作流。 如果工作流引发未处理的异常,则会调用 OnUnhandledException 处理程序。 从 OnUnhandledException 返回三个可能的作,这些作决定了工作流的最终结果。

  • 取消 - 取消的工作流实例是分支执行的正常退出。 可以建模取消行为(例如,使用 CancellationScope 活动)。 取消过程完成后,将调用 Completed 处理程序。 已取消的工作流处于“已取消”状态。

  • 终止 - 无法恢复或重启终止的工作流实例。 这会触发 Completed 事件,你可以在该事件中提供异常作为终止原因。 终止进程完成后,将调用终止处理程序。 终止的工作流处于故障状态。

  • 中止 - 仅当已将其配置为持久时,才能恢复中止的工作流实例。 如果没有持久性,则无法恢复工作流。 在工作流中止时,由于最后一个持久性点丢失,因此执行的任何工作(内存中)。 对于中止的工作流,将使用异常调用 Aborted 处理程序,作为中止进程完成的原因。 但是,与“已取消”和“终止”不同,不会调用已完成处理程序。 中止的工作流处于中止状态。

以下示例调用引发异常的工作流。 该异常由工作流未经处理,并调用 OnUnhandledException 处理程序。 将检查 WorkflowApplicationUnhandledExceptionEventArgs 以提供有关异常的信息,并终止工作流。

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();

使用 TryCatch 活动处理异常

使用 TryCatch 活动处理工作流中的异常。 TryCatch 活动具有与特定 Exception 类型关联的 Catch 活动的 Catches 集合。 如果 TryCatch 活动 Try 节中包含的活动引发的异常与 Catches 集合中 Catch<TException> 活动的异常匹配,则会处理异常。 如果显式重新引发异常或引发新异常,则此异常将传递给父活动。 下面的代码示例演示一个 TryCatch 活动,该活动处理 Throw 活动在 Try 节中引发的 ApplicationException。 异常的消息由 Catch<TException> 活动写入控制台,然后在 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."
    }
};

Finally 节中的活动在 Try 节或 Catches 节成功完成时执行。 如果未从该节引发异常,Try 节将成功完成,如果未引发或重新引发异常,Catches 部分将成功完成。 如果在 TryCatchTry 节中引发异常,并且不是由 Catches 节中的 Catch<TException> 处理,或者从 Catches重新引发,则除非发生以下事件之一,否则不会执行 Finally 中的活动。

异常处理与补偿

异常处理和补偿之间的区别在于异常处理在执行活动期间发生。 补偿在活动成功完成后发生。 异常处理提供了在活动引发异常后清理的机会,而补偿提供了一种机制,通过该机制可以撤消以前完成的活动的成功完成工作。 有关详细信息,请参阅 补偿

另请参阅