前段时间应客户要求,需要把工作流设计成每个节点(stateActivity)都需要自由跳转.
比如有一个工作流画好的模板,按工作顺序运行下来就是:输入->提交服务->输出.
当开发业务的时候,写业务的程序员必须要加载这工作流模板,按设计好的顺序运行,写的逻辑只写输入时要怎么处理,输出时要怎么处理而已.
不过,要允许在这个工作流的这几个节点间暴露可以重写的方法,以便可以在每个节点运行前后作一些自己要处理的逻辑.
现在他们要在这些重写的代码中加入GOTO语句,可以自由写GOTO把工作流的状态改变,比如,当运行到结束点前时,发现最后得到的数据中有不满意的地方要重新运行,就必须可以写一个GOTO(stepname);直接跳到开始节点.
一开始以为很容易实现.没做太大的考虑就答应了.
后台真正做到时,才发现是有问题的,在当前工作流实例线程正在运行时,是不能随意的用SETSTATE()方法改变状态,要改的话WF只支持,预先设计好到达这个节点会有什么情况,然后用IFELSEActivity再改变流转.但这样的确太死,就是说你要做到所有情况都必须考虑好,然后在画工作流时设计好.这样就满足不了以后情况有变化的问题,多一个条件就得改一次工作流图加多一个判断,如果条件非常多,比如有几十个以上,那这个图我想必定混乱了.
后来终于想了一个技巧去解决这个问题,就是按照状态机的事件驱动方式去处理,但发送事件的是要新开一个线程去处理,这样第一个线程在处理到这个外部节点时如果需要GOTO就起另一个线程去SETSTATE,当然,在GOTO前,调用业务处理的代码比较完成并且返回到,状态机便处于等待状态,这样用第二个线程去SETSTATE就不会有问题了.
说得有点乱,以后再整理一下,如果那位朋友也遇到此类问题可以一起探讨解决.目前我的这个问题已经可以解决,当然还必须要做一下优化.
最后,简单的贴一下相关的代码:
#region 异步线程GOTO到目标步骤
public static void GoTo(WFSubmitContext context)
{
Thread td = new Thread(new ParameterizedThreadStart(GotoNextSetp));
td.IsBackground = true;
td.Start(context);
}
static void GotoNextSetp(object data)
{
WFSubmitContext context = data as WFSubmitContext;
string nextStep = context.Parameters["GotoStep"] as string;
if (string.IsNullOrEmpty(nextStep)) throw new Exception("要跳转的目标步骤名不能为空!");
StateMachineWorkflowInstance stateInstance = new StateMachineWorkflowInstance(Runtime, context.InstanceID);
stateInstance.SetState(nextStep);
}
#endregion
浙公网安备 33010602011771号