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是单线程运行的

 

 

  1. 当所有分支中的结点都执行完成后,该Parallel结点才结束,继续向下执行
  2. 每分支不是在一个独立的线程上运行的,而是在同一线程中作为一个独立的任务队列运行

 

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时,其他与上例相同

流程

结果

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 适合毕业设计、课程设计作业。这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。 所有源码均经过严格测试,可以直接运行,可以放心下载使用。有任何使用问题欢迎随时与博主沟通,第一时间进行解答!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值