在.NET Workflo“.NET研究”w 3.5中使用多线程提高工作流性能

  最近在工作上碰到一个性能问题,由于项目是基于SOA的架构,使得整个系统完全依赖于各种各样的Serv上海闵行企业网站制作ice,其中用于处理业务逻辑的Business Services全部都用.NET Workflow 3.5实现(历史原因,项目还没升级到Workflow 4)。在众多的Business Service中,其中有一个的主要功能是,通过调用不同的Data Service来获取数据,然后根据业务逻辑来组织这些数据并返回给它的调用者。该Business Service的工作流(Workflow)主要包含三个活动组件(Activity),大致可以用下图表示:

  需要说明一下,在实际项目中,这个Workflow本身不仅仅只是简单地包含上面三个Activity,通过性能测试的数据分析,瓶颈就在这三个Activity上,而每个Activity的执行时间又主要消耗在反复调用Data Service上。在此,为了简化问题的描述,我把其它不相干的Activity剔除了,于是就得到了上图的结构。

  图中的三个Activity都会分别去调用不同的Data Service来获得数据,尤其在getNotesActivity中,Data Service会被循环调用,这使得系统性能大打折扣。原本有一个解决方案可以在一定程度上提高getNotesActivity的效率,就是修改被调用的Data Service,使得它能够一次性接收多个request的数据,处理完之后再将所有的结果一次性返回,这样就避免了Data Service的循环调用,有效地减少了数据在网络上的来回次数。但是,这种解决方案需要更改Data Service的Request Schema,这个改动是很大的,因为可能有很多其它的Business Service都在调用这个Data Service,牵涉的范围太广了。

  根据实际项目,稍加分析不难发现,这个Workflow中的Activity有如下几个特点:

  • 三个Activity的输入属性参数都来自于Workflow(即通过与Workflow中定义的DependencyProperty进行绑定而获得数据),并不存在下游的Activity的输入参数需要依赖上游Activity的输出参数的情况
  • 每个Activity的输出属性参数都只关注某一种类型的数据,在Workflow Runtime执行完某个Activity后,也会通过DependencyProperty将处理结果传递给Workflow,而这些输出属性参数之间也并没有任何关联
  • 三个Activity所调用的Data Service也比较独立,基本上可以说是在做三个完全不同的工作
  • 时间主要消耗在Data Service的调用上,不存在由于复杂的运算逻辑导致CPU利用率近似100%的情况,也不存在由于物理内存用完而需要频繁读写虚拟内存的情形

  上述的几个特点中,第四点为我们引入多线程或并行任务处理提供了主要依据。这里需要额外岔开一下。有很多软件人员认为,多线程一定能够提高系统性能,因为事务可以分派到多个线程中进行并行处理。我觉得,应该这样去看待这个问题:首先,根据Martin Fowler的《企业应用架构模式》(也就是著名的PoEAA)一书中有关性能的讨论认为,有很多术语可以描述性能,比如:响应时间、响应性、等待时间、吞吐率、负载、负载敏感度上海企业网站设计与制作等。假设完成某个任务需要的时间很长,比如需要5秒,那么其响应时间就是5秒,而如果让用户等待这5秒过去后,再将系统的控制权交给用户,就会让用户明显感觉很不顺上海网站建设,于是响应性就很差;但如果能将这个任务交给另一个执行体去处理,而程序本身直接将系统控制权交给用户,等那个执行体完成任务处理后,再将结果提供给用户,那么,同样处理这个任务需要5秒钟,这种方式的响应性就明显要好于前者,这也是我们以前做Windows Forms开发的时候,要把耗时的处理交给另一个线程处理,以不至于因为主线程的阻塞而导致界面冻结的尴尬局面。因此,多线程的引入,可以提高系统的响应性。

  其次,多线程是否能够提高系统的响应时间?这也未必,在单核处理器上,多线程是采用时间片轮循的方式实现的,也就是说,相同时间点上,只有一个线程在执行,只不过是时间片足够小,轮循频率足够高,才让我们感觉线程是并行执行的,在这样一种体系结构下,完成任务的处理还是需要那么长时间,甚至时间片的切换倒还会带来额外的开销。在多核系统中,或许真的可以提高响应时间,不过我目前没有实际的测试数据用来比较,因此在这个问题上,我还没有足够的发言权。

  而对于目前项目的情况,Data Service是分布在网络上不同位置的资源,如果能让这些Data Service同时处理数据请求,再让Business Service去组织分别来自这些Data Service的处理结果,那么整个Business Service的响应时间是可以明显提高的,响应时间提高了,响应性也同样提高了。假设第一个Activity耗时t1,第二个Activity耗时t2,第三个Activity耗时t3,那么,如果按上图中的顺序方式执行,Business Service的响应时间就是t1+t2+t3。但如果让这些Activity并行处理(也就相当于并行调用Data Service使其同时处理数据请求),那么Business Service的响应时间应该就是max(t1, t2, t3)。

  于是,我打算将上述的Workflow修改一下,采用多线程的方式来分别运行每个Activity,最后再将结果汇总。我修改后的Workflow如下所示:

上海闵行企业网站设计与制作"0" alt="image" width="579" height="349" />

  在此需要对ParallelActivity说明一下。.NET Workflow 3.5的ParallelActivity并没有做到所谓的并行执行,因为Workflow Runtime是在单独的线程上执行Workflow Instance的,因此,要让多个Activity真正并行执行是做不到的。ParallelActivity的真正用意在于协调每个分支中的SequenceActivity(注意:ParallelActivity的每个分支只能接收一个SequenceActivity),使得其中的每个Activity都有一次执行的机会。

  某个分支中的一个活动执行过后,就会轮到下一个分支。当这个分支执行了一个活动后,执行又会转移到再下一个分支,以此类推。当所有分支都有了执行机会之后,又会从第一个(最左侧)分支开始这一过程,继续执行第一个分支的下一个活动(如果存在的话)。因此,在我们的这个例子中,完全可以不用ParallelActivity,而仍然选择原来的结构即可。之前我并没有完全清楚地了解ParallelActivity,开始一直以为ParallelActivity的意思是,让Workflow Runtime同时安排(Schedule)每个分支的执行,以便当每个分支都以异步方式运行时,所有的分支可以实现并行处理。

  不过也不要紧,在这里使用ParallelActivity,虽然没有有效地利用它的特性,但与原来的Workflow相比,从可读性上讲,这种结构更容易让人觉得这是一种并行的运行方式。

  另一个变化是,原本每个操作都是写在一个自定义的Activity中的,通过重写Activity的Execute方法来做业务处理,而现在则是用CodeActivity来代替原来的Activity,这样做的好处是,可以将业务处理的代码放在同一个Context中,这也为线程同步提供了便利,降低了使用线程的复杂度。

  以下是改进后的Workflow的代码,供参考。


1. using System;
2. using System.Collections.Generic;
3. using System.Threading;
4. using System.Workflow.Activities;
5. namespace WorkflowConsoleApplication3
6. {
7. public sealed partial class Workflow1 : SequentialWorkflowActivity
8. {
上海徐汇企业网站设计与制作> 9. List<Thread> threads = new List<Thread>();
10. public Workflow1()
11. {
12. InitializeComponent();
13. }
14. private void getAdditionalInfoActivity_Execute(object sender, EventArgs e)
15. {
16. var t1 = new Thread(() =>
17. {
18. // Call Data Service 1 to implement business logic...
19. });
20. threads.Add(t1);
21. t1.Start();
22. }
23. private void getNotesActivity_Execute(object sender, EventArgs e)
24. {
25. var t2 = new Thread(() =>
26. {
27. // Call Data Service 2 in a loop to implement business
28. // logic...
29. });
30. threads.Add(t2);
上海徐汇企业网站制作31. t2.Start();
32. }
33.
34. private void getSpecialPointsActivity_Execute(object sender, EventArgs e)
35. {
36. var t3 = new Thread(() =>
上海企业网站制作an>37. {
38. // Call Data Service 3 to implement business logic...
39. });
40. threads.Add(t3);
41. t3.Start();
42. }
43.
44. private void syncCodeActivity_Execute(object sender, EventArgs e)
45. {
46. // Wait for all threads to terminate...
47. threads.ForEach(p => p.Join());
48. // TODO: Process with results and exceptions
49. }
50. }
51. }
52. 从上面的代码中可以看到,每个

  从上面的代码中可以看到,每个CodeActivity在执行的时候都会启动一个线程,这个线程会调用相应的Data Service来实现其业务逻辑,线程创建以后,会被保存在一个线程列表里,用来在syncCodeActivity中进行线程同步。syncCodeActivity则通过线程的Join方法来等待所有线程全部完成各自的工作,最后对运行结果和异常进行处理。

  此处线程的运用需要遵循.NET线程使用的最佳实践,应该尽量避免线程的阻塞,在访问临界资源的时候应作加锁处理以防止状态异常。由于在这个例子中,每个线程又会牵涉到其它Service的调用,因此在线程中捕获的异常,我建议还是先将其记录下来,然后温和地直接使用return语句终止线程执行,而不是随意抛出异常而使得线程进入一个不确定的状态。当然,读者朋友如果在多线程环境中有处理异常的经验,也恳请在本文留言指导。

  对Workflow进行调整之后,重新编译、部署并运行这个Business Service,然后用已经写好的Client程序进行测试,我们得到了如下的结果(几个明显的噪音数据已经被划掉,没有包含在统计中)。从这个报表可以看到,针对我们的这个案例,在Workflow中引入多线程的确可以明显地提高系统性能。

时间: 2024-09-27 23:27:41

在.NET Workflo“.NET研究”w 3.5中使用多线程提高工作流性能的相关文章

《中国人工智能学会通讯》——11.34 基于近似动态规划的优化控制研究及 在电力系统中的应用

11.34 基于近似动态规划的优化控制研究及 在电力系统中的应用 上世纪 50 年代以来,在空间技术发展和数字计算机实用化的推动下,动态系统的优化理论得到了迅速的发展,形成了一个重要的学科分支--最优控制[1-2] .它在空间技术.系统工程.多级工艺设备的优化等领域都有越来越广泛的应用.因而更深入研究最优控制问题,无论在理论上,还是在实践上都具有重大的意义.最优控制理论的三大基石是经典变分理论.极小值原理及动态规划.经典变分理论只能解决控制无约束问题,即容许控制属于开集的一类最优控制问题,而工程

数据研究在交互设计中的应用

交互设计师一大宝贵财富就是他的经验和直觉,在大多数需要对当前设计作出迅速判断的情况中,交互设计师所依赖的就是他的经验和直觉.在互联网的世界中,最有价值的可能就是数据了.google靠数据一举奠定江湖地位:twitter靠数据开始逐渐走向成熟:每一个交互设计师也能用数据来弥补依靠经验和直觉来设计的不足.本篇网志从一个很小的设计案例来描述除了经验和直觉之外,http://www.aliyun.com/zixun/aggregation/13083.html">数据研究也可以验证.修正.甚至颠覆

用户研究设计:实际工作中总结用户访谈经验心得

文章描述:最近做了一些项目的用户访谈,总结出些许经验心得,这里先就一些访谈过程的关键点作为一个开头,后续再来补充其他技巧等方面,大家也可以共同补充,同时欢迎大家拍砖. 最近做了一些项目的用户访谈,总结出些许经验心得,这里先就一些访谈过程的关键点作为一个开头,后续再来补充其他技巧等方面,大家也可以共同补充,同时欢迎大家拍砖. 1.明确用研目的 研究目的是做用户研究首要需明确的问题.产品的需求是否可以通过用研来解决,如果可以解决,采用哪种方法,是定量还是定性,定性是座谈会还是用户访谈等等,这都要根据

交互设计研究:视觉注意力在设计中的运用

物质世界客观存在,而人的"视觉成像"是对当前世界的"唯心"重建.这种重建基于个人"经验"."感知"和"集体意识".最初科学家认为人类通过视觉被动获取周围世界的全部图像信息而建立个人的视觉资料库,近10年来的研究表明捕获"全部图像信息"只是个传说,其中由心理学家Daniel T. Levin 和Daniel J. Simons建立的实验"真实世界"客观说明一个事实:大脑

有谁研究过在JavaME中解析条形码?

问题描述 哪位大哥研究过过在JavaME中解析条形码呀,刚涉足这块领域,请教了! 解决方案 解决方案二:没研究过用过的也都是各个系统本地语言编写的跟LZ等待高人解决方案三:在google里面搜索zxing,这个可以解析二维码和条形码,不过成功率不是特别高.这个是google的开源项目..解决方案四:我试过了,用自己照的就不能识别了,估计是照片拍的不清晰解决方案五:楼主这个vodafone的图...我也有.O(∩_∩)O哈哈~widget?哪个??解决方案六:Nothingisimpossible

使用 MEF 公开 Silverlight“.NET研究” MVVM 应用程序中的接口

下载代码示例 许多开发人员可能都将 Silverlight 视为以 Web 为中心的技术,但实际上,它已经成为构建任何应用程序的优秀平台. Silverlight 本身就支持许多概念,例如数据绑定.值转换器.导航.浏览器外操作和 COM 互操作,因此它可以相对直观简便地创建任何种类的应用程序. 我说的是"任何种类",其中当然也包括企业级应用程序. 利用 Model-View-ViewModel (MVVM) 模式来创建 Silverlight 应用程序,这使您除了能够使用 Silver

欧洲专家研究发现上班玩网游能提高工作效率

日前,国外专家研究发现,上班时间玩网络游戏更有益于提高工作效率. 这项研究来自以一名欧洲专家对上班时间玩游戏的假设:经常进行电子放松(cyberslacking),对员工个生产力会有较大的提升.这个情况最先发现于员工们的日常工作情绪,当员工接到大量的连续工作任务时,他们的身心上都会比较疲惫,进而开始影响和减低工作效率.要快速赶走这种情绪,最好的方法是插入一些与工作完全无关的事情.研究者称,如果要达到有效而快速的治愈效果,以下4点是必不可少的: 1.与工作完全脱离,彻底忘掉工作 2.可以让心情放松

用户体验研究:携程酒店订房中的日期选择

用了一下携程酒店订房中的日期选择. 有几个有趣的现象. 用户应该都明白,今天不可能去订昨天的房间.比如今天是12月8号,你只能从今天起始的房间,不能去订昨天的房间.如果你"选择"了12月7号,网站会提示"入住时间不能早于200-12-8". 由于设计上的原因,用户可以根据一定的格式自行输入日期,用户不能从日历中选择已过去的日期,但仍然可以输入,所以用户会"选择"了一个已过去的日期. 如果用户选择今天入住,今天离店,网站会提示"离店时间不

Flash关于游戏制作研究之在场景中移动(二)

自从那篇游戏场景移动之一后,现在我们制作另一种场景移动的方式.这次我们要做的形式就是当游戏角色超出一定范围后才滚动场景. 这种方式需要我们先给出一个角色可以移动的范围,只要游戏角色一超出这个范围地图就开始移动.知道相关的东西后我们就开始编写脚本把,其实我们不用再重新写一遍这个脚本,只要用我在第一篇提供的源码上作修改就能够容易地得出这种方式的场景移动了,那我们现在来看源代码吧:import flash.geom.Rectangle; //引入矩形类包 var rect:Rectangle = ne