C# 作为工作流故障切换的工作流持久性和书签
我有一组自定义活动,用于复杂的工作流 我想让它们(自定义活动)持久化,而不让工作流处于空闲状态。它应该是一种故障切换系统,因此在工作流执行过程中出现问题时,它可以是:C# 作为工作流故障切换的工作流持久性和书签,c#,workflow-foundation-4,workflow-foundation,workflow-activity,sqlworkflowpersistencese,C#,Workflow Foundation 4,Workflow Foundation,Workflow Activity,Sqlworkflowpersistencese,我有一组自定义活动,用于复杂的工作流 我想让它们(自定义活动)持久化,而不让工作流处于空闲状态。它应该是一种故障切换系统,因此在工作流执行过程中出现问题时,它可以是: 由用户暂停(在anytime中),然后从暂停的书签/点恢复(例如,用户注意到外部系统已关闭,他希望暂时暂停工作流) 如果出现未处理的异常,我们可以从最后一个书签/时间点重新开始执行 WorkflowApplication主机可以随时停止,我们可以从最后一个书签/时间点重新启动执行 我已经用工作流持久性工作了几天,但我不确定我是
- 由用户暂停(在anytime中),然后从暂停的书签/点恢复(例如,用户注意到外部系统已关闭,他希望暂时暂停工作流)
- 如果出现未处理的异常,我们可以从最后一个书签/时间点重新开始执行
- WorkflowApplication主机可以随时停止,我们可以从最后一个书签/时间点重新启动执行
- 我可以在每个自定义活动中使用阻止书签,但是仅仅为了持久化而阻止工作流并重新启动它看起来不太可能
- 我可以使用notblocking书签,但我无法在数据库中看到它们并从中恢复李>
PersistOnClose
,它足以满足我的需求。
在wf4中,它被Persist
activity替换,这可能也很有用,但是我不希望在已经很复杂的工作流中有额外的活动
理想情况下,能够从
NativeActivityContext
执行context.RequestPersist(callback)
,这将非常好,但是这个方法是内部的(并且它内部的所有内容在原始程序集之外都不可见)。如果我正确理解您的问题,那么您有以下要求
如有任何问题和定制要求,请与我所讨论的相同。:)因为我开发了与您类似的工作流程 以下是我带来的:
- 非阻塞书签不是一个选项。尽管非阻塞书签不会阻止创建活动的完成,但它也不会导致工作流实例变为空闲状态,这意味着它不会被持久化。一旦创建非阻塞书签的活动完成,非阻塞书签将被丢弃。只有在创建活动尚未完成时,才能恢复此书签
- 使用
不是一个选项,因为我使用的是WF4,而该属性仅为.NET 3.x WFPersistOnCloseAttribute
- 无法使用阻止书签,因为它们阻止工作流的执行,这是不需要的李>
Persist
活动(必须扩展可以安排子活动的NativeActivity
):
为了使其正常工作,必须将其作为ImplementationChild添加到元数据中:
protected override void CacheMetadata(NativeActivityMetadata metadata)
{
base.CacheMetadata(metadata);
metadata.AddImplementationChild(this.childActivity);
}
最后一件事是从Execute方法调度子活动(无论在何处,持久性只会在调用活动完成后发生*)
为了在未处理的异常之后保持工作流的持久性,必须将以下代码段添加到WorkflowApplication:
application.OnUnhandledException = delegate(WorkflowApplicationUnhandledExceptionEventArgs e)
{
return UnhandledExceptionAction.Abort;
};
*从Execute
方法返回并不一定意味着该活动已“完成”-即活动内有阻塞书签(见下文)
此解决方案有几个缺点:
- 解决方案只保留工作流的一种状态(最后一种状态)
- 只有在活动完成时才能发生持久性。这意味着不能从活动的中间进行持久化/恢复
- 它不适用于并行循环/序列-并行循环/序列中的活动在整个并行过程完成后被持久化。它可以正确地处理常规循环/序列
- 阻止书签对此解决方案有很大影响(如果它们是在创建活动或创建活动的其他子活动中创建的)。它们导致活动未完成,即使返回Execute方法。最终将执行Persist(在活动完成后或进入空闲状态之前)
protected override void Execute(NativeActivityContext context)
{
//...
context.ScheduleActivity((Activity)this.childActivity);
}
application.OnUnhandledException = delegate(WorkflowApplicationUnhandledExceptionEventArgs e)
{
return UnhandledExceptionAction.Abort;
};