WF4.0 基础篇 (十四) Delay 与WF4中的线程
本节主要介绍WF的实例是单线程运行的,Delay并不是Thread.Sleep,Parallel是单线程运行的,WorkflowApplication与WorkflowInvoker在调用流程上的区别,InvokeMethod 调用异步方法
本文例子下载:
http://files.cnblogs.com/foundation/DelayAndThreadWorkflow.rar
本文例子说明
WF的实例是单线程运行的
在WF3.x与WF4.0中,工作流实例都是单线程执行的
很多时候,[Parallel]给人一种多线程并行运行的感觉,实际上,Parallel是在单线程中轮换执行各分支。
这是一篇我在2006年写的关于WF3.x中Parallel的运行说明 http://www.cnblogs.com/foundation/archive/2006/10/10/525630.html
同时本文也会在后面的讲解中对WF4.0的[Parallel]运行方式加以说明
Delay 延时
类名 |
System.Activities.Statements.Delay |
文件 |
System.Activities.dll |
结构说明 |
继承 NativeActivity 是一个 sealed类 override 了 [CacheMetadata方法] 与 [Execute方法] 与 [Cancel 方法] 与 [Abort方法] override 了[CanInduceIdle 属性] [Duration] 属性 的类型为[InArgument<System.TimeSpan>] |
功能说明 |
1.延迟,按指定的时间阻止当前的工作流执行。 持续时间过期后,工作流继续执行 2.[Duration]属性,表示阻止当前的工作流执行的时间 3.会触发实例的[OnIdel],但在[WorkflowApplicationIdleEventArgs.Bookmarks]中无[Bookmark] |
例:基本使用
1.在流程中添加一个[WriteLine],打印系统时间
2.在流程中添加一个[],时间为[10秒]
3.在流程中再添加一个[WriteLine],打印系统时间
流程 |
|
宿主 |
#region //Delay 例子 static void workflowCompleted(WorkflowApplicationCompletedEventArgs e) { System.Console.WriteLine("完成,实例编号:{0},状态:{1}", e.InstanceId, e.CompletionState.ToString()); } static void workflowIdle(WorkflowApplicationIdleEventArgs e) { System.Console.WriteLine("Idle,实例编号:{0}", e.InstanceId); foreach (var item in e.Bookmarks) { System.Console.WriteLine("BookmarkName:{0}", item.BookmarkName); } } static void delayWorkflow() { WorkflowApplication instance = new WorkflowApplication(new DelayWorkflow()); instance.Completed = new Action<WorkflowApplicationCompletedEventArgs>(workflowCompleted); instance.Idle = workflowIdle; instance.Run(); } #endregion |
结果 |
Delay并不是Thread.Sleep ,Parallel是单线程运行的
- 当所有分支中的结点都执行完成后,该Parallel结点才结束,继续向下执行
- 每分支不是在一个独立的线程上运行的,而是在同一线程中作为一个独立的任务队列运行
ParallelActivity以下图方式周期性的查看每个分支队列中的第一项,如果是可执行的Activity就执行,如果是不可执行的,(如Delay没到期或挂起没被外部触发)就跳过,执行过程如下
例:Parallel是单线程运行的
1.创建一个code Activity,[ThreadSleepActivity],在[Execute]中[Thread.Sleep(10000)]
2.在工作流中添加一个[Parallel],并添加两个分支
分支一:添加[ThreadSleepActivity],添加[WriteLine]打印系统时间
分支一:添加[ThreadSleepActivity],添加[WriteLine]打印系统时间
ThreadSleepActivity |
public sealed class ThreadSleepActivity : CodeActivity { protected override void Execute(CodeActivityContext context) { System.Threading.Thread.Sleep(10000); } } |
工作流 |
|
宿主 |
WorkflowInvoker.Invoke(new ThreadSleepParallelWorkflow()); |
结果 |
[Parallel]是用单线程完成分支的,所以两个[ThreadSleepActivity],的[Thread.Sleep(10000)]共产生了20秒的延时 如果[Parallel]是用多线程完成分支的,两个并行的[Thread.Sleep(10000)]会只产生了10秒的延时 |
例:Delay并不是Thread.Sleep
如果将[例:Parallel是单线程运行的]中的[ThreadSleepActivity]换为[Delay]会有什么效果
1.在工作流中添加一个[Parallel],并添加两个分支
分支一:添加[Delay]延时10秒,添加[WriteLine]打印系统时间
分支一:添加[Delay]延时10秒,添加[WriteLine]打印系统时间
工作流 |
|
宿主 |
WorkflowInvoker.Invoke(new DelayParallelWorkflow()); |
结果 |
结合[例:Parallel是单线程运行的],可以得出Delay并不是Thread.Sleep Delay的实现原理我会在后面的文章中详细说明 |
WorkflowApplication与WorkflowInvoker在调用流程上的区别
在WF4.0中,可以使用WorkflowApplication与WorkflowInvoker创建并启动实例.
但两者在宿主中的线程方式是不一样的
使用WorkflowInvoker启动工作流时,工作流将附加到宿主的线程中执行
使用WorkflowApplication启动工作流,工作流实例将在宿主线程之外的另一个线程中运行,使用的是线程池方式
例:WorkflowInvoker启动工作流
1.创建一个code activity,[runtimeTestActivity],在[Execute]中循环打印1到10
2.在工作流程添加[runtimeTestActivity]
3.在宿主中用WorkflowInvoker方式启动该工作流的两个实例
runtimeTestActivity |
public sealed class runtimeTestActivity : CodeActivity { protected override void Execute(CodeActivityContext context) { for (int i = 1; i <= 10; i++) { System.Threading.Thread.Sleep(500); System.Console.WriteLine(i); } } } |
流程 |
|
宿主 |
static void workflowInvoker() { WorkflowInvoker.Invoke(new runtimeTestWorkflow()); WorkflowInvoker.Invoke(new runtimeTestWorkflow()); } |
结果 |
可以当第一个实例完成后,第二个实例才启动 |
例:WorkflowApplication启动工作流
1.创建一个code activity,[runtimeTestActivity],在[Execute]中循环打印1到10
2.在工作流程添加[runtimeTestActivity]
3.在宿主中用WorkflowApplication方式启动该工作流的两个实例
runtimeTestActivity |
public sealed class runtimeTestActivity : CodeActivity { protected override void Execute(CodeActivityContext context) { for (int i = 1; i <= 10; i++) { System.Threading.Thread.Sleep(500); System.Console.WriteLine(i); } } } |
流程 |
|
宿主 |
static void workflowApplication() { WorkflowApplication instance1 = new WorkflowApplication(new runtimeTestWorkflow()); WorkflowApplication instance2 = new WorkflowApplication(new runtimeTestWorkflow()); instance1.Run(); instance2.Run(); } |
结果 |
第一个实例启动后,第二个实例也启动了,两个实例是同时在两个线程上运行 |
InvokeMethod 调用异步方法
由于WF的实例是单线程运行,在用InvokeMethod调用方法时,就存在二种情况,是在实例的线程内调用方法还是在实例的线程外调用方法.
[InvokeMethod 调用方法]一节的内容都是在实例的线程内调用方法,现在介绍一下用InvokeMethod 异步调用方法
当[InvokeMethod]所调用的方法中的线程时,可以将[InvokeMethod]的[RunAsynchronously]属性设为[True]以实现等待调用的方法中的线程完成.
要使[RunAsynchronously]属性有效,需要用如下方式设计方法
1.为要实现该功能的方法添加如下两个方法 IAsyncResult Begin[原史方法] ([原史方法参数], AsyncCallback callback, object asyncState) void End[原史方法] (IAsyncResult r) 2.当[RunAsynchronously]属性设为[False]时, [InvokeMethod]调用[原史方法] 3.当[RunAsynchronously]属性设为[True]时, [InvokeMethod]调用对应的[Begin原史方法]与[End原史方法]方法 4.如果没的提供与[原史方法]对应的[Begin原史方法]与[End原史方法]方法, [InvokeMethod]将忽略[RunAsynchronously]属性的值 MethodName属性的[Begin原史方法]和[End原史方法]不会调用,调用的是[原史方法] |
InvokeMethod 调用异步方法时等待异步方法完成后,流程才继续向下执行
实现这种调用方式的关键是[IAsyncResult]接口的[CompletedSynchronously 属性]要返回[false]
1.定义实现[IAsyncResult]接口的[myAsyncResult]
public class myAsyncResult : IAsyncResult { public object AsyncState { get; set; } public System.Threading.WaitHandle AsyncWaitHandle { get; set; } public bool CompletedSynchronously { get { return false; } } public bool IsCompleted { get { return true; } } } |
2.一个用于[InvokeMethod]调用的[threadMethod]类
提供一个[myCall],有一个参数n,该方法用于实现计算1到n的累加值,并在屏幕上打印
[threadMethod]类提供了正常的[myCall]方法,以及为[InvokeMethod]的[RunAsynchronously]使用的[BeginmyCall]与[EndmyCall]方法
public class threadMethod { AsyncCallback callback; IAsyncResult asyncResult; int n; int result; public void myCall ( int n ) { for (int i = 1; i <= n; i++) { result = result + i; } System.Console.WriteLine("myCal, resultl:{0}", result); } public IAsyncResult BeginmyCall ( int n , AsyncCallback callback, object asyncState) { System.Console.WriteLine("BeginmyCall,n:{0}", n); this.n = n; this.callback = callback; this.asyncResult = new myAsyncResult() { AsyncState = asyncState }; System.Threading.Thread thread = new System.Threading.Thread(new System.Threading.ThreadStart(myProcessThread)); thread.Start(); return this.asyncResult; } public void EndmyCall (IAsyncResult r) { Console.WriteLine("EndmyCall, result:{0}",result); } public void myProcessThread() { Console.WriteLine("myProcessThread"); for (int i = 1; i <= n; i++) { result = result + i; System.Console.WriteLine(i); System.Threading.Thread.Sleep(500); } this.callback(this.asyncResult); } } |
3. 工作流,宿主,结果
工作流 |
|
宿主 |
#region // InvokeMethod 异步调用方法例子 static void threadMethodWorkflow() { WorkflowApplication instance = new WorkflowApplication(new threadMethodWorkflow()); instance.Completed = completed; instance.Run(); } static void completed(WorkflowApplicationCompletedEventArgs e) { System.Console.WriteLine("流程完º成"); } #endregion |
结果 |
要注意的是[InvokeMethod]只调用了 BeginmyCall 与 EndmyCall 方法,并没调用 myCall 方法 |
InvokeMethod 调用异步方法后不等待异步方法完成后就继续向下执行
实现这种调用方式的关键是[IAsyncResult]接口的[CompletedSynchronously 属性]要返回[true]
1.定义实现[IAsyncResult]接口的[myAsyncResult]
public class myAsyncResult : IAsyncResult { public object AsyncState { get; set; } public System.Threading.WaitHandle AsyncWaitHandle { get; set; } public bool CompletedSynchronously { get { return true; } } public bool IsCompleted { get { return true; } } } |
其他与上例相同
结果 |
要注意的是[InvokeMethod]并没调用 myCall 方法 [InvokeMethod]调用完 BeginmyCall 方法后就立即调用 EndmyCall 方法,并没有等待 [ myProcessThread() ]的完成 |
RunAsynchronously属性设为False时,只执行[原史方法]
将[InvokeMethod.RunAsynchronously]属性设为False时,其他与上例相同
流程 |
|
结果 |
WF4.0 基础篇 (十四) Delay 与WF4中的线程相关推荐
- WF4.0 基础篇 (十八) Flowchar
本节主要介绍WF4 中 Flowchart的使用 本文例子下载: http://files.cnblogs.com/foundation/FlowcharSample.rar 本文例子说明 Flowc ...
- WF4.0 基础篇 (三十 完) 对学习WF的一点建议
从09年10月份 NET4.0 Bata 2发布后,我就开始写[WF4.0 基础篇]这个系列,经历了5个多月终于在NET4.0正式发布前将这个系列完成了 这段时间与一些对WF4.0感兴趣的公司与开发人 ...
- [转]WF4.0 基础篇 (一)开始使用WF
本文转自:http://www.cnblogs.com/foundation/archive/2009/10/26/1589993.html 来博客园写WF主题博客已经3年了, 在园子里认识了很多朋友 ...
- WF4.0 基础篇 (二) Activity介绍及WriteLine Activity的使用
从本篇开始,将正式讲解WF4.0,本文主要涉及如下内容:Activity介绍, WF4.0 中工作流的结构,通过WriteLine演示InArgument<T>参数的使用 目录 1 ...
- WF4.0 基础篇 (二十八) WF调用PowerShell
PowerShell 提供了命令行管理系统的功能,但通常情况下,操作人员要完成某种业务需要多组PowerShell 命令,这样会很烦琐,错误率也比效高.操作人员可以编写powerShell脚本来组织命 ...
- WF4.0 基础篇 (二十九) WorkflowInspectionServices
本文例子下载: http://files.cnblogs.com/foundation/WorkflowInspectionServicesSample.rar WorkflowInspectionS ...
- WF4.0 基础篇 (二十六) Interop调用WF3.X的Activity
本节主要介绍Interop调用WF3.X的Activity 本文例子下载: http://files.cnblogs.com/foundation/InteropSample.rar 本文例子说明 I ...
- WF4.0 基础篇 (三) 流程实例WorkflowApplication与设计WF程序的基本原则
通过本节,可以初步了解WF程序的特性,为以后的WF类应用开发提供一个初步的感性认识 目录 1 流程实例WorkflowApplication与设计WF程序的基本原则 1 1.1 流程 ...
- WF4.0 基础篇 (六) 数据的传递 Arguments 参数
节主要介绍如何在WF4.0中使用参数,以及在流程启动时传入参数据在流程结束时读取参数 本文例子下载: http://files.cnblogs.com/foundation/ArgumentsSamp ...
最新文章
- JS每日一题: 小程序页面之间如何通信?
- java 保护内存操作的方法
- java 求数组最大子序列之和
- android自动软键盘,Android自定义软键盘
- linux脚本传参修改配置文件,shell脚本修改配置文件指定行的值
- spring源码学习
- html 字体样式 幼圆,设置字体样式:字号大小,字体种类,字体粗细
- go技术文章精选(2019)
- 解决小程序图片上传问题
- Linux-v10-01天-授课
- 记录一次实战破解无线wifi——Aircrack-ng
- tomcat启动一直卡在Root WebApplicationContext: initialization completed
- 1.5 人工智能迅速发展的技术领域
- 自定义 iPhone 铃声
- 西安硬科技创新大会前奏,一起玩转陕西首档广播双创节目乐创power
- IDC许可证是什么证?IDC办理条件及材料
- 2021年全球与中国重型泥浆泵行业市场规模及发展前景分析
- 电子支付与网上银行1
- 洛谷 P1070 [NOIP2009 普及组] 道路游戏 题解
- 《C#设计模式》【装饰者模式】
热门文章
- 最新的三星android版本是多少,三星3代Android大版本更新名单出炉,S9/Note9被抛弃
- AudioTrack: releaseBuffer() track 0xe5c6bc00 disabled due to previous underrun, restarting
- 如何下载WDK10【详见本文的中文注解】
- Java学习历程之----提升篇(六)
- 惠普指纹识别和PIN不能使用的一种原因
- 给女朋友推送睡前小故事
- 前端 圆形进度图_js圆形进度的实现,可以自定义进度图标
- java 时间字符串 转换_java实现时间与字符串之间转换
- mysql时间与字符_mysql时间与字符串之间相互转换
- BeautifulReport测试报告的bootstrap文件失效(404)