WF4.0 基础篇 (十四) Delay 与WF4中的线程
来源:互联网 发布:java生成jar文件 编辑:程序博客网 时间:2024/05/02 00:29
本节主要介绍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 例子
staticvoid workflowCompleted(WorkflowApplicationCompletedEventArgs e)
{
System.Console.WriteLine("完成,实例编号:{0},状态:{1}", e.InstanceId, e.CompletionState.ToString());
}
staticvoid workflowIdle(WorkflowApplicationIdleEventArgs e)
{
System.Console.WriteLine("Idle,实例编号:{0}", e.InstanceId);
foreach (var itemin e.Bookmarks)
{
System.Console.WriteLine("BookmarkName:{0}", item.BookmarkName);
}
}
staticvoid 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
publicsealed class ThreadSleepActivity : CodeActivity
{
protectedoverride void Execute(CodeActivityContext context)
{
System.Threading.Thread.Sleep(10000);
}
}
工作流
宿主
WorkflowInvoker.Invoke(newThreadSleepParallelWorkflow());
结果
[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(newDelayParallelWorkflow());
结果
结合[例: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
publicsealed class runtimeTestActivity : CodeActivity
{
protectedoverride void Execute(CodeActivityContext context)
{
for (int i =1; i <= 10; i++)
{
System.Threading.Thread.Sleep(500);
System.Console.WriteLine(i);
}
}
}
流程
宿主
staticvoid workflowInvoker()
{
WorkflowInvoker.Invoke(newruntimeTestWorkflow());
WorkflowInvoker.Invoke(newruntimeTestWorkflow());
}
结果
可以当第一个实例完成后,第二个实例才启动
例:WorkflowApplication启动工作流
1.创建一个code activity,[runtimeTestActivity],在[Execute]中循环打印1到10
2.在工作流程添加[runtimeTestActivity]
3.在宿主中用WorkflowApplication方式启动该工作流的两个实例
runtimeTestActivity
publicsealed class runtimeTestActivity : CodeActivity
{
protectedoverride void Execute(CodeActivityContext context)
{
for (int i =1; i <= 10; i++)
{
System.Threading.Thread.Sleep(500);
System.Console.WriteLine(i);
}
}
}
流程
宿主
staticvoid workflowApplication()
{
WorkflowApplication instance1 =new WorkflowApplication(newruntimeTestWorkflow());
WorkflowApplication instance2 =new WorkflowApplication(newruntimeTestWorkflow());
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]
publicclass myAsyncResult :IAsyncResult
{
publicobject AsyncState
{
get;set;
}
public System.Threading.WaitHandle AsyncWaitHandle
{
get;set;
}
publicbool CompletedSynchronously
{
get
{
returnfalse;
}
}
publicbool IsCompleted
{
get
{
returntrue;
}
}
}
2.一个用于[InvokeMethod]调用的[threadMethod]类
提供一个[myCall],有一个参数n,该方法用于实现计算1到n的累加值,并在屏幕上打印
[threadMethod]类提供了正常的[myCall]方法,以及为[InvokeMethod]的[RunAsynchronously]使用的[BeginmyCall]与[EndmyCall]方法
publicclass threadMethod
{
AsyncCallback callback;
IAsyncResult asyncResult;
int n;
int result;
publicvoid myCall ( int n )
{
for (int i =1; i <= n; i++)
{
result = result + i;
}
System.Console.WriteLine("myCal, resultl:{0}", result);
}
publicIAsyncResult 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();
returnthis.asyncResult;
}
publicvoid EndmyCall (IAsyncResult r)
{
Console.WriteLine("EndmyCall, result:{0}",result);
}
publicvoid 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异步调用方法例子
staticvoid threadMethodWorkflow()
{
WorkflowApplication instance =new WorkflowApplication(newthreadMethodWorkflow());
instance.Completed = completed;
instance.Run();
}
staticvoid completed(WorkflowApplicationCompletedEventArgs e)
{
System.Console.WriteLine("流程完º成");
}
#endregion
结果
要注意的是[InvokeMethod]只调用了BeginmyCall 与EndmyCall 方法,并没调用myCall 方法
InvokeMethod 调用异步方法后不等待异步方法完成后就继续向下执行
实现这种调用方式的关键是[IAsyncResult]接口的[CompletedSynchronously 属性]要返回[true]
1.定义实现[IAsyncResult]接口的[myAsyncResult]
publicclass myAsyncResult :IAsyncResult
{
publicobject AsyncState
{
get;set;
}
public System.Threading.WaitHandle AsyncWaitHandle
{
get;set;
}
publicbool CompletedSynchronously
{
get
{
returntrue;
}
}
publicbool IsCompleted
{
get
{
returntrue;
}
}
}
其他与上例相同
结果
要注意的是[InvokeMethod]并没调用myCall 方法
[InvokeMethod]调用完BeginmyCall 方法后就立即调用EndmyCall 方法,并没有等待 [ myProcessThread() ]的完成
RunAsynchronously属性设为False时,只执行[原史方法]
将[InvokeMethod.RunAsynchronously]属性设为False时,其他与上例相同
流程
结果
- WF4.0 基础篇 (十四) Delay 与WF4中的线程
- WF4.0 基础篇 (二十四) Async Activity
- WF4.0 基础篇 (四) 顺序容器Sequence 与CodeActivity
- WF4.0 基础篇 (四) 顺序容器Sequence 与CodeActivity
- WF4.0 基础篇 (二十五) ActivityAction 与 InvokeAction
- WF4.0 基础篇 (二十五)(补充) ActivityFunc 与 InvokeFunc
- WF4.0与多线程
- WF4.0 基础篇 (十六) CompensableActivity 补偿
- WF4.0 基础篇 (十七) Bookmark
- WF4.0 基础篇 (十八) Flowchart
- WF4.0 基础篇 (二十一) WorkflowInvoker
- WF4.0 基础篇 (二十二) Tracking
- WF4.0 基础篇 (二十九) WorkflowInspectionServices
- wf4
- WF4.0 基础篇 (三) 流程实例WorkflowApplication与设计WF程序的基本原则
- .WF4.0 基础篇 (七) 数据的传递 变量与参数的使用
- WF4.0 基础篇 (三) 流程实例WorkflowApplication与设计WF程序的基本原则
- WF4.0 基础篇 (七) 数据的传递 变量与参数的使用
- 15-Android界面控件之TextView的一些属性
- 中科院分词ICTCLAS5.0_JNI 使用方法
- volatile语义及线程安全singleton模式探讨
- 强迫自己学习(实践篇),以及关于写博客的几点建议
- 百度笔试总结
- WF4.0 基础篇 (十四) Delay 与WF4中的线程
- Android下QQ空间查看大图特效
- Write a function to find the longest common common string amongst an array of strings.
- windows下用VS2010 build ceres solver 库
- android listview item定义不同的样式布局
- 十亿数据中求最大一百个数字
- 2014华为校园招聘机考(10.12北京)
- mongodb_分布式存储_切片
- if语句中判断两值是否相等的小技巧