使用本地服务异步执行自定义活动业务逻辑

简介:

通常情况下我们开发的自定义活动的业务逻辑都是写在Execte方法中的,由于一个工作流实例在单一的线程上执行,这样当工作流在执行到这个活动的时候,该活动就独占了整个工作流的线程,如果该自定义活动需要做很长时间的任务,那么此时就不能处理工作流中的其他请求。所以我们不建议把所有的业务逻辑都放到Execute方法中去执行。

1.我们可以将活动的业务逻辑放到本地服务中去异步执行,下面我们用一个例子来说明,建立一个顺序型工作流控制台项目,首先我们先写两个类CaryWork和CaryWorkResult,分别代表我们要执行的工作项和返回的结果,代码如下:

[Serializable]
public class CaryWork
{
    public Guid InstanceId { get; set; }
    public String WorkItem { get; set; }
    public String ResultQueueName { get; set; }

    public CaryWork( Guid InstanceId, String ResultQueueName, String WorkItem)
    {
        this.InstanceId = InstanceId;
        this.ResultQueueName = ResultQueueName;
        this.WorkItem = WorkItem;
    }
}
[Serializable]
public class CaryWorkResult
{
   public String Result { get; set; }
public CaryWorkResult(String Result) { this.Result = Result; } }

ResultQueueName 表示返回结果的队列名称。
InstanceId表示工作流的id 
WorkItem 表示要执行的任务


2.然后我们开始编写本地服务的部分,首先声明一个接口,接口中的方法将会在自定义活动中调用,代码如下:
public interface ILongTaskServices
{
   voidDoLongTaskWork(CaryWorkworkToDo);
}

然后实现该接口,代码如下:

public class LongTaskServices : WorkflowRuntimeService,ILongTaskServices
{
   private Random _random = new Random();

   public void DoLongTaskWork(CaryWork workToDo)
   {
       ThreadPool.QueueUserWorkItem(TPWorkCallback, workToDo);
       Console.WriteLine("工作项队列: {0}",workToDo.WorkItem);
   }       

   private void TPWorkCallback(Object state)
   {
       CaryWork workitem = state as CaryWork;
       WorkflowInstance instance = Runtime.GetWorkflow(workitem.InstanceId);            
       Int32 msw = _random.Next(1000, 5000);
       Thread.Sleep(msw);
       CaryWorkResult response = new CaryWorkResult(String.Format(
"工作项-{0}返回-{1}", workitem.WorkItem, msw)); instance.EnqueueItem(workitem.ResultQueueName, response, null, null); } }
在本地服务中我们使用线程池来执行我们要完成的任务,我们使用Thread的Sleep方法假定每项任务要执行的时间,完
成后会返回CaryWorkResult对象。
 
3.现在我们实现我们的自定义活动,代码如下:
public partial class LongTaskActivity : Activity,IActivityEventListener<QueueEventArgs>
{
public static DependencyProperty WorkItemProperty = DependencyProperty.Register("WorkItem", typeof(string), typeof(LongTaskActivity)); [DescriptionAttribute("WorkItem")] [BrowsableAttribute(true)] [DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Visible)] public string WorkItem { get{ return ((string)(base.GetValue(LongTaskActivity.WorkItemProperty)));} set{ base.SetValue(LongTaskActivity.WorkItemProperty, value);} } private String queueName = Guid.NewGuid().ToString(); public LongTaskActivity() { InitializeComponent(); } protected override ActivityExecutionStatus Execute(ActivityExecutionContext executionContext) { ILongTaskServices longRunningService=executionContext.GetService(typeof
(ILongTaskServices)) as ILongTaskServices; WorkflowQueuingService queueService= executionContext.GetService(typeof
(WorkflowQueuingService))as WorkflowQueuingService;
WorkflowQueue queue = queueService.CreateWorkflowQueue(queueName, true); queue.RegisterForQueueItemAvailable(this); CaryWork request = new CaryWork(this.WorkflowInstanceId, queueName, WorkItem); Console.WriteLine("调用本地服务: {0}", WorkItem); longRunningService.DoLongTaskWork(request); return ActivityExecutionStatus.Executing; } public void OnEvent(object sender, QueueEventArgs e) { ActivityExecutionContext aec = sender as ActivityExecutionContext; WorkflowQueuingService queueService = aec.GetService<WorkflowQueuingService>(); WorkflowQueue queue = queueService.GetWorkflowQueue(e.QueueName); if (queue != null && queue.Count > 0) { CaryWorkResult response = queue.Dequeue() as CaryWorkResult; if (response != null) Console.WriteLine("结果为: {0}", response.Result); } queueService.DeleteWorkflowQueue(e.QueueName); aec.CloseActivity(); }
}
在自定义活动中我们去调用本地服务的方法来执行工作项,queue工作流队列被创建,Execute方法中返回
ActivityExecutionStatus.Executing表示工作项没有执行完成,完成后会在OnEvent事件中向控制台输出结果,并调
用AEC的CloseActivity方法来关闭活动。
 
4.设计工作流,我们在工作流设计器中拖一个ParallelActivity活动,并向每个分支中拖入一个我们自定义的活动,
并设置其WorkItem属性,如图:
 
 
5.在宿主程序我们需要加载本地服务到工作流引擎中,代码如下:
static void Main(string[] args)
{
    using(WorkflowRuntime workflowRuntime = new WorkflowRuntime())
    {
        AutoResetEvent waitHandle = new AutoResetEvent(false);
        workflowRuntime.WorkflowCompleted += delegate(object sender,WorkflowCompletedEventArgs e)
{waitHandle.Set();}; workflowRuntime.WorkflowTerminated+=delegate(object sender,WorkflowTerminatedEventArgs e) { Console.WriteLine(e.Exception.Message); waitHandle.Set(); }; workflowRuntime.AddService(new LongTaskServices()); WorkflowInstance instance = workflowRuntime.CreateWorkflow(typeof
(CaryLongWF.LongTaskWorkflow)); Console.WriteLine("---工作流执行开始---"); instance.Start(); waitHandle.WaitOne(); Console.WriteLine("---工作流执行结束---"); } }
 
6.运行程序执行结果如下:

 

从结果上我们有的时候会看到WorkItem1和WorkItem2的顺序会颠倒,这是因为我们在本地服务中做了随机的Sleep动作。


本文转自生鱼片博客园博客,原文链接:http://www.cnblogs.com/carysun/archive/2008/11/01/LongActivity.html,如需转载请自行联系原作者

相关文章
|
26天前
|
设计模式 Java Spring
【Spring源码】WebSocket做推送动作的底层实例是谁
我们都知道WebSocket可以主动推送消息给用户,那做推送动作的底层实例究竟是谁?我们先整体看下整个模块的组织机构。可以看到handleMessage方法定义了每个消息格式采用不同的消息处理方法,而这些方法该类并**没有实现**,而是留给了子类去实现。
17 0
【Spring源码】WebSocket做推送动作的底层实例是谁
|
1天前
|
Java Android开发
Android系统 获取用户最后操作时间回调实现和原理分析
Android系统 获取用户最后操作时间回调实现和原理分析
6 0
|
8月前
|
缓存 NoSQL 前端开发
若依系统(分离版)后台接口被调时,代码哪里判断了token是否超时?
若依系统(分离版)后台接口被调时,代码哪里判断了token是否超时?
484 0
|
9月前
|
存储 缓存 小程序
自己动手之小程序自定义登录态维护
谈起小程序开发,想必大家都不会陌生了。众所周知,小程序开发的官方文档是要求开发者需要自行维护登录态的。那么小程序服务端开发的登录态维护大家是如何做的呢?本文适用微信和QQ小程序的自定义登录态维护。
178 0
自己动手之小程序自定义登录态维护
|
10月前
|
前端开发 Java 数据安全/隐私保护
基于拦截器实现线上演示站点只能查看不可操作得要求
基于拦截器实现线上演示站点只能查看不可操作得要求
51 0
|
人工智能 负载均衡 监控
支付宝定时任务怎么做?三层分发任务处理框架介绍
本文将从单机定时调度开始,循序渐进地带领大家了解五福定制三层分发任务处理框架。
24536 3
支付宝定时任务怎么做?三层分发任务处理框架介绍
|
缓存 数据库
项目启动时执行指定任务如何实现?
项目启动时执行指定任务如何实现?
项目启动时执行指定任务如何实现?
activiti 全局流程监听ActivitiEventListener,实现监听不同类型事件,不需要在acitivit中配置任务监听,非常方便
activiti 全局流程监听ActivitiEventListener,实现监听不同类型事件,不需要在acitivit中配置任务监听,非常方便
853 0
activiti 全局流程监听ActivitiEventListener,实现监听不同类型事件,不需要在acitivit中配置任务监听,非常方便
|
前端开发
前端工作小结93-重置逻辑
前端工作小结93-重置逻辑
53 0
|
前端开发
前端工作小结79-重置逻辑
前端工作小结79-重置逻辑
60 0

热门文章

最新文章