通常情况下我们开发的自定义活动的业务逻辑都是写在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动作。
发表评论
-
平淡的2007
2007-12-24 08:04 817早上起来,送女朋友去公交车站,然后回来赶紧打开电脑,先 ... -
DreamSpark发布,高校学生免费使用Visual Studio 2008 Professional Edition 等微软软件
2008-02-20 13:23 1415今天上网无意中搜索到学生可以免费使用VS2008专业版,后来又 ... -
坚持学习WF(1):从HelloWorld开始
2008-04-04 16:30 892[置顶]坚持学习WF文章索 ... -
坚持学习WF(2):WF创作模式和设计时工具
2008-04-05 17:19 639[置顶]坚持学习WF文章索 ... -
坚持学习WF(3):WF框架概览
2008-04-08 07:27 783[置顶]坚持学习WF文章索 ... -
坚持学习WF(4):活动(Activity)和依赖属性(DependencyProperty)
2008-04-12 00:01 1148[置顶]坚持学习WF文章索引 活动(Activity) 活动 ... -
坚持学习WF(5):自定义活动(CustomActivity)
2008-04-13 15:25 929当WF提供的标准活动不能满足我们的需求的时候,我们就需要定义自 ... -
MOSS点滴(1):如何开发和部署feature
2008-04-16 21:35 836Features 是MOSS 2007以开箱即用的一套新功能, ... -
MOSS点滴(2):自定义Application Page
2008-04-19 20:07 844在MOSS中后台管理的页面都是Application Pag ... -
坚持学习WF(6):开发可复用的宿主程序
2008-04-21 21:45 695我们之前写工作流宿主 ... -
MOSS点滴(3):说说MOSS中的母版页
2008-04-25 21:15 1189MOSS中有两种页面:Site P ... -
MOSS点滴(4):实现Form认证
2008-04-29 21:12 705本文主要参考了网上的一些文章,但有些文章有些地方说的不是很明确 ... -
坚持学习WF(7):流程控制(Flow Control)
2008-04-30 18:10 839本文主要说说WF中和流 ... -
坚持学习WF(8):本地服务之调用外部方法
2008-05-09 08:17 761WF提供了一组核心服务 ... -
MOSS中的WebPart开发
2008-05-10 13:53 1060由于在asp.net1.1的时候asp.net中还没有webp ... -
坚持学习WF(9):本地服务之事件处理
2008-05-28 07:49 800[置顶]坚持学习WF文章索引 一:先来介绍两个活动 Even ... -
坚持学习WF(10):在工作流中使用关联
2008-06-01 13:03 692[置顶]坚持学习WF文章索 ... -
坚持学习WF(11):工作流通信与队列
2008-06-07 15:45 736[置顶]坚持学习WF文章索引 WF 提供的通信模型是构建于 ... -
MOSS中创建自定义内容类型
2008-06-12 20:23 1107一:简要介绍 某类内容 ... -
.NET中IDisposable接口的基本使用
2008-06-15 12:01 950首先来看MSDN中关于这个接口的说明: [ComVisible ...
相关推荐
4. **服务提供者处理**:服务提供者接收到请求后,反序列化数据,执行对应的业务逻辑,然后将结果再次序列化并返回给服务消费者。 5. **结果处理**:服务消费者接收到响应后,对结果进行反序列化,完成调用过程。 ...
自定义按钮可以绑定特定的函数,例如执行一段JavaScript代码或发送Ajax请求,以实现特定的业务逻辑。 4. **安装与集成** 首先,你需要从KindEditor官方网站下载最新版本的源码包,然后将包含CSS、JavaScript和图片...
8. **数据绑定**:除了使用默认的数据源绑定,还可以实现自定义的数据绑定逻辑,支持更复杂的数据模型。 9. **行状态管理**:可以添加额外的行状态信息,如行的选中、禁用、高亮等,通过自定义属性来实现。 10. **...
这样,当用户在Webview中选择城市后,可以选择调用原生方法来更新应用的状态或执行其他业务逻辑。 4. **数据加载**:城市数据可能来自本地资源文件,也可能通过网络API获取。本地数据可以通过JSON格式存储,然后在...
6. **业务逻辑服务层**: - 定义一个`GenAiTaskService`,它是业务逻辑的中心,负责处理GenAI任务的状态转换。这里可以集成GenAI算法,如训练模型或执行NLP任务。 7. **状态转换逻辑**: - 实现RAG状态转换逻辑,...
在自定义轮播图中,可以为每个图片添加点击监听器(OnClickListener),当用户点击图片时,触发相应的回调方法,执行开发者预设的操作,比如跳转到详情页面或者执行其他业务逻辑。 最后,"无限轮播"是指当图片轮播...
它提供了一个模型-视图-控制器(MVC)架构,帮助开发者分离业务逻辑、数据处理和用户界面。在没有Tomcat的情况下,Spring MVC仍然可以处理路由、请求处理和视图渲染,但是由于不支持JSP,我们需要寻找其他方式来呈现...
15.3.3 创建业务逻辑层 492 15.3.4 创建数据访问层 494 15.4 小结 497 第16章 使用ObjectDataSource控件 498 16.1 使用ObjectDataSource控件表示对象 498 16.1.1 绑定到组件 499 16.1.2 绑定到DataReader 500 ...
Observable负责监听网络请求或本地缓存,Subscriber则负责订阅这些事件并在适当的时候执行相应的操作,如将新图片加载到视图或者更新缓存。 具体实现步骤如下: 1. 创建一个LRUCache实例,作为图片缓存容器。...
"坚持学习WF(11)工作流通信与队列"关注WF如何与其他组件或服务进行通信,可能包括使用队列进行异步通信的场景。 "坚持学习WF(12)使用EventHandlingScopeActivity活动"更进一步,专门讲解EventHandlingScopeActivity...
这些库封装了复杂的异步加载、内存管理、缓存策略等细节,让开发者能更专注于业务逻辑。 总之,异步加载图片是Android开发中的核心技能之一,通过理解和实践这个Demo,开发者可以深入理解Android应用的性能优化,并...
CRM4.0还允许开发人员创建复合插件,即多个插件组合成一个逻辑单元,以及使用工作流活动与插件配合,实现更复杂的业务逻辑。 总结来说,CRM4.0中的Plug-In提供了一种灵活的方式,让企业能够根据自身需求定制CRM...
在Mule中,可以使用flows、patterns和服务来组织和执行业务逻辑。指南会详细说明它们之间的区别以及在特定场景下应该如何选择。 3. **服务编排**: 当涉及到多个服务交互时,flows的使用将变得至关重要。使用...
这些类库包含了特定业务逻辑,当特定事件触发时(如创建、更新或删除记录),系统会执行这些逻辑。插件可以是同步的,与主要操作同时执行,也可以是异步的,以避免阻塞用户界面。 插件注册工具的使用通常涉及以下几...
【RSS资源后台服务】是一...通过自动化RSS信息的抓取和处理,它可以帮助开发者减轻维护负担,专注于更高级别的业务逻辑开发。同时,提供的源码意味着用户可以根据自身需求进行定制和扩展,增强了系统的适应性和灵活性。
根据请求内容,服务端执行相应的业务逻辑,如数据库查询、计算等,并将结果封装成响应返回给访问者。 为了使通信双向化,服务端需要有能力不仅发送数据,还能接收来自访问者的反馈。这可能涉及到长连接、WebSocket...
在IT行业中,用户体验是至关重要的一个方面,尤其是在处理复杂业务逻辑和数据加载时。"业务加载中显示等待图片"这个话题直接关乎用户界面(UI)的设计和用户体验(UX)。当用户进行操作,如点击按钮、提交表单或加载...
总之,"Delphi调用WebService生成unit的WebService unit文件的工具"是一个非常实用的功能,它简化了Delphi与Web服务之间的交互,使开发者能更专注于业务逻辑,而不是底层通信细节。通过导入WSDL文件并生成对应的Unit...
在提供的压缩包"255 可本地执行,样式齐全的demo.rar"中,包含了Layui的tree组件的示例代码,这将帮助我们更深入地理解和使用Layui Tree。 首先,Layui Tree是一个用于展示层级关系数据的组件,通常用于目录结构、...
总的来说,这个项目提供了一种高效且优雅的方式来调用HTTP接口,使Android开发者能更专注于业务逻辑,而不是网络通信的底层实现。它通过代理模式和注解驱动的设计,实现了HTTP调用的自动化,提升了开发体验。在实际...