程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> 關於.NET >> WF 4.0 基礎篇(十四) Delay與WF4中的線程

WF 4.0 基礎篇(十四) Delay與WF4中的線程

編輯:關於.NET

本節主要介紹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("流程完o成");
}
#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時,其他與上例相同

相同

流程 結果
  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved