补偿(Compensation)

基本概念

首先我们来回顾下事务的加锁机制。事务在提交之前会加锁记录以防止来自其它执行过程的查询.但是长期加锁事务不仅磨灭程序的可伸缩性,甚至会造成死锁。

所谓补偿,简单的说就是时空隧道,对之前做过的正确的事情重新做一遍。它抛开锁机制去尽可能快的提交事务并继续执行.如果之后某一点发生了错误,我们再去弥补之前完成的事务,也许这样做并不能逆转事务,但我们可以采取其它的措施(譬如取消)来弥补这个事务失败所造成的影响。

WF3.5,我们只能补偿实现了ICompensatableActivity接口的活动.在基本活动库中,CompensatableSequenceActivityCompensatableTransactionScopeActivity都实现了这个接口.。(待核实)

4.4.3 CompensatableSequenceActivity

CompensatableSequenc活动的功能相当于附加了补偿处理程序(Compensation Handler)Sequence活动.我们可以通过右键菜单的View Compensation Handler来查看补偿处理器视图

在补偿处理程序视图中,我们可以添加活动来对其子活动进行补偿。

4.4.4 CompensatableTransactionScopeActivity

CompensatableTransactionScope活动的功能相当于附加了补偿处理程序的TransacionScope,所以CompensatableTransactionScope活动也不能包含CompensatableTransactionScope活动作为其子活动.

CompensatableTransactionScope活动的补偿处理程序视图中,我们可以使用活动来定义补偿的逻辑.

记住,补偿只当被补偿活动顺利完成时才会生效.

 

4.4.5 CompensateActivity

我们只能补偿实现了ICompensatableActivity接口的活动.除了刚才提到的这两个基本活动库中的活动之外,我们还可以创建实现ICompensatableActivity接口的自定义活动.

Compensate活动的TargetActivityName属性指定需要补偿的活动,Runtime就会执行目标活动的补偿处理程序.Compensate活动只能存在于错误处理程序或补偿处理程序中.当此活动在补偿处理程序中时,它还可以引发其子活动事务的补偿. 或许这里让人有些难以理解,我再解释一下:

可以把Compensate活动视作一个触发器,它可以触发目标活动的补偿处理程序,使其进行补偿.

使用Compensate进行补偿的目标活动必须实现ICompensatableActivity接口,而且一定要顺利完成,因为我们之前提到,所谓补偿就是一个”亡羊补牢”的过程,错误的产生和发现应该是在事务提交之后,此时Compensate活动需要置于错误处理程序中.

如果某个可补偿的活动内部还包含了可补偿的子活动(比如嵌套的CompensatableSequence活动),而且其子活动在提交事务之后的某一步发生了错误,那么在这个活动(而不是它的子活动)的补偿处理程序中添加Compensate活动可以对此错误进行补偿.

定义补偿

简述

Compensate活动用来补偿之前完成的并且需要补偿的活动。因此

CompenationHandler当工作流有异常或活动执行取消完成后方执行;

ConfirmationHandler为工作流正常执行完成后方执行;

CancellationHandler为活动取消时方执行。

Result:活动执行结果的参数。

代码方式实例:

new CompensableActivity

                                    {

                                        Body = new WriteLine { Text = " CompensableActivity: Do First Action" },

 

                                        ConfirmationHandler = new WriteLine { Text = " CompensableActivity: Confirm First Action" },

                                        CompensationHandler = new WriteLine { Text = " CompensableActivity: Compensate First Action" },

                                        CancellationHandler = new WriteLine { Text = " CompensableActivity: Cancel First Action" },

                                        Result = tokenA

                                    },
声明方式实例:

因为使用xaml进行定义,xml属于声明式编程(Declarative program)的一种。

显式调用补偿活动

使用Confirm来显式调用CompensationHandler活动,使用Compensate显式调用ConfirmationHandler活动。

使用CompensationToken

CompensationToken,用来通过记录发放令牌来安排补偿活动的执行顺序。

关于CompensableActivity容器中活动的执行顺序

1、  当流程完成时会自动调用CompensableActivity容器自动执行所有[CompensableActivity]中的ConfirmationHandler

2、  只有为 [实例.OnUnhandledException]指定[ UnhandledExceptionAction.Cancel]时,当流程在[CompensableActivity]的外部产生异常,才会自动调用[CompensableActivity]中的CompensationHandler

3、  只有为 [实例.OnUnhandledException]指定[ UnhandledExceptionAction.Cancel]

4、  当流程在[CompensableActivity][Body]部分产生异常,才会自动调用[CompensableActivity]中的CompensationHandler

CancellationHandler CompensationHandler的区别

当异常发生在[CompensableActivity]外部时,会调用 [CompensationHandler]

当异常发生在[CompensableActivity.Body]部分时,会调用 [CancellationHandler] [CompensationHandler]可以被[Compensate] 显示调用

5、  显示调用的时候,活动的执行顺序

显式调用CompensableActivity

使用[Confirm]可以显示调用[CompensableActivity][ConfirmationHandler]部分

使用[Compensate]可以显示调用[CompensableActivity][CompensationHandler]部分

要显示调用[CompensableActivity],需要定义一个[ System.Activities.Statements.CompensationToken]型变量,[CompensableActivity][Result]绑定到该变量上.再将[Confirm][Compensate][Target]属性绑定到该变量上即可实现显示调用

一个[CompensableActivity]只能被调用一次.调用两次以上会出错

如果[Confirm]调用后,[Compensate]再调用会出错

如果[Compensate]调用后,[Confirm]再调用会出错

[Confirm][Compensate]调用后,不会再被自动调用

显式调用Confirm活动

当在流程中用[Confirm]调用其所对应的[CompensableActivity][ConfirmationHandler],[ConfirmationHandler]中的内容会被立即执行,这与自动调用不同

显式调用compensate活动

当在流程中用[Compensate]调用其所对应的[CompensableActivity][CompensationHandle],[CompensationHandle]中的内容会被立即执行,这与自动调用不同

显示调用[Compensate],不需要为 [实例.OnUnhandledException]指定[ UnhandledExceptionAction.Cancel]

6、多个/嵌套 CompensableActivity 容器

无异常时,如果有多个[CompensableActivity][CompensableActivity]有嵌套时,[ConfirmationHandler]执行顺序是:

在同级别容器中,是从下向上[ConfirmationHandler],在嵌套容器中是从外向内[ConfirmationHandler]

有异常,但异常不在CompensableActivity中时

如果有多个[CompensableActivity][CompensableActivity]有嵌套时,[ConfirmationHandler][CompensationHandler]执行顺序是:

6.1.如果产生异常的[Activity][CompensableActivity]在同级别容器中,则该级别的[CompensableActivity]会执行[ConfirmationHandler].

[CompensableActivity]嵌套的[CompensableActivity]会执行[ConfirmationHandler]

6.2、异常在CompensableActivity中时

如果有多个[CompensableActivity][CompensableActivity]有嵌套时,[ConfirmationHandler][CompensationHandler][CancellationHandler]执行顺序是:

*如果产生异常的[Activity][CompensableActivity]在同级别容器中,则该级别的[CompensableActivity]会执行[ConfirmationHandler].

[CompensableActivity]嵌套的[CompensableActivity]会执行[ConfirmationHandler]

*.如果产生异常的[Activity][CompensableActivity]具有[父子孙]的直接层级关系,会调用这些具有[父子孙]直接层级关系[CompensableActivity][CancellationHandler]

7TerminateWorkflow 不会触发CompensableActivity的任何行为

官方实例
eg1
简单的补偿活动

简介:在正常的执行顺序中,使用补偿活动给将要做的定义的工作。这个工作在晚点有必要去补偿这个动作。

相关知识点:

使用ManualResetEvent来创建一个线程供application来运行。

// Executing the sequence of two actions that complete with success

            Console.WriteLine("Execution with success:");

            application = new WorkflowApplication(BuildASequenceofCompensableActions());

            ManualResetEvent resetEvent = new ManualResetEvent(false);          

            application.Completed = delegate(WorkflowApplicationCompletedEventArgs e)

            {

                resetEvent.Set();

            };

            application.Run();

            resetEvent.WaitOne();

 

eg2取消引发的补偿活动

简介:使用补偿范围来分组一系列可补偿的活动集,使它们与其他补偿范围相隔离。

相关知识点
CompensationToken
,用来通过记录发放令牌来安排补偿活动的执行顺序。

eg3 客制化补偿

简介:使用补偿和补偿处理器来定义客制化的补偿逻辑。

eg4 分布式补偿

简介:使用补偿实现工作流服务宿主并行运作。

疑问:

CompensableActivityCompensate的区别:前者是后者的集合。(有待验证)

posted @ 2010-01-06 08:31  风影极光  阅读(1259)  评论(0编辑  收藏  举报