代码之家  ›  专栏  ›  技术社区  ›  Ronald Wildenberg

尽管Trycatch活动,异常仍从工作流中逸出

  •  1
  • Ronald Wildenberg  · 技术社区  · 14 年前

    我在Windows服务中有一个工作流,它是一个周期性执行工作的循环。这项工作是在 TryCatch 活动。这个 Try 属性是 TransactionScope 包装一些读取和更新数据库的自定义活动的活动。当事务失败时,我希望任何导致此错误的异常 Trycatch公司 . 但是,我的工作流中止。我的工作流程如下:

    var wf = new While(true)
    {
        Body = new Sequence
        {
            Activities =
            {
                new TryCatch
                {
                    Try = new TransactionScope
                    {
                        IsolationLevel = IsolationLevel.ReadCommitted,
                        Body = new Sequence
                        {
                            Activities = { ..custom database activities.. }
                        },
                        AbortInstanceOnTransactionFailure = false
                    },
                    Catches =
                    {
                        new Catch<Exception>
                        {
                            Action = new ActivityAction<Exception>
                            {
                                Argument = exception,
                                Handler = ..log error..
                            }
                        }
                    }
                },
                new Delay { Duration = new InArgument<TimeSpan>(duration) }
            }
        },
    }
    

    在我的例子中,数据库有时可能不可用,所以很明显事务不会提交。在这种情况下,会发生以下异常,导致工作流中止:

    System.OperationCanceledException:处理当前工作项时出错,导致工作流中止。

    内部异常是:

    System.Transactions.TransactionException:操作对于事务状态无效。

    这很有意义,因为我刚关闭了数据库。但是,为什么我的 Trycatch公司 活动?

    编辑1 :一些附加信息。我使用 WorkflowApplication 类。为了更好地了解发生了什么,我指定了属性 Aborted OnUnhandledException . 当异常发生时,它直接转到 已中止 ONUNHANDDException公司 跳过(尽管这显然是未处理的异常)。

    编辑2 :我启用了调试日志,这提供了一些额外的细节。“自定义数据库活动”已成功运行到完成。第一个表示有问题的事件日志条目是详细级别的消息: 运行时事务已完成,状态为“已中止” . 接下来,我看到一条信息消息: WorkflowInstance ID:'DBD1BA5C-2D8A-428C-970D-215D7E06D9'E2E活动 (不知道这意味着什么)。之后的信息是: 活动“System.Activities.Statements.TransactionScope”,DisplayName:“用于立即运行检查的事务”,InstanceID:“389”已在“Faulted”状态下完成 .

    在这条消息之后,我看到每个家长(包括 Trycatch公司 活动)在“错误”状态下完成,以我的工作流中止结束。

    编辑3 :要清楚,当任何“自定义数据库活动”中发生异常时,一切都将按预期工作。捕获异常并继续工作流。只有当事务在 交易范围 . 请参阅以下StackTrace 已中止 回拨:

    at System.Transactions.TransactionStateInDoubt.Rollback(InternalTransaction tx, Exception e)
    at System.Transactions.Transaction.Rollback(Exception e)
    at System.Activities.Runtime.ActivityExecutor.CompleteTransactionWorkItem.HandleException(Exception exception)
    

    如果你接电话 TransactionScope.OnCompletion(...) 最终你会到达 ActivityExecutor StackTrace中的类。

    2 回复  |  直到 14 年前
        1
  •  5
  •   Ron Jacobs    14 年前

    事务在事实发生后异步提交。由于资源管理器级别的问题,无法对提交事务失败做出响应。

    正如您所指出的,您可以处理在您的活动中发生的异常。如果您查看工作流的跟踪记录,我猜想您将看到Trycatch活动在事务中止之前关闭。

    许多年前,当我还是COM+团队的项目经理时,我研究了这个问题,因为人们通常希望事务组件(或工作流)能够对事务中止做出反应。

    事务解析的异步性质意味着您无法在组件本身中对其作出响应。解决方案是在调用者中做出反应,然后可以采取一些行动。

    设计假设是,一旦一个事务中止,就不能安全地使用事务中有关状态aqcuired的任何内容,因为该事务中止,所有内容都将被丢弃。

        2
  •  2
  •   Maurice    14 年前

    所以只需加上罗恩的回答。这里的唯一选项是添加sqlWorkflowInstanceStore,并在TransactionScope之前除去一个持久活动。当事务中止时,整个工作流将中止,但过去保存的状态仍将在持久性数据库中,工作流可以从此以前保存的状态重新启动,然后再次执行事务。