天天看點

.Net的異步機制(線程間通信) - step 5

前幾篇文章我已經對異步的操作進行的詳細的解釋.異步操作也是線程的一種,當我們開始一個異步操作(新線程),完成調用後需要和其他線程通信(可能需要告知狀态資訊),這時候我們就需要線程間的通信程式設計.

線程間通信

我們看下面的圖

.Net的異步機制(線程間通信) - step 5

圖1

我們來看線程間通信的原理:線程(Thread B)和線程(Thread A)通信, 首先線程A 必須實作同步上下文對象(Synchronization Context), 線程B通過調用線程A的同步上下文對象來通路線程A,所有實作都是在同步上下文中完成的.線程B有兩種方式來實作線程間的通信.

第一種:調用線程A的同步上下文對象,阻礙目前線程,執行紅色箭頭調用,直到黃色箭頭傳回(同步上下文執行完畢)才釋放目前線程. (1->2->3->5)

第二種: 調用線程A的同步上下文對象(實際上是在開啟一個新線程去執行,1->2->3->5) ,執行紅色箭頭,但并不阻礙目前線程(原有線程,1->4->5),綠色箭頭繼續執行.

文章中将會通過下面幾個類來進行介紹:

1.        

ISynchronizeInvoke

接口

2.        

SynchronizationContext 類

3.        

AsyncOperation / AsyncOperationManager 類

附:  同步上下文對象(Synchronization Context)是什麼呢? 當我們通路上下文對象時候(多個對象可以存在于一個上下文中), 是使用代理的方式引用的,而不是直接引用的.這種方式可能是當多個對象通路上下文對象時候,先到達對象先通路,鎖住,執行完畢再解鎖,排隊式通路.

1.

ISynchronizeInvoke

接口

我們先來看下面一段異步的代碼(Window Form控件下有1個Button/1個Label),但點選Button的時候,執行異步調用,完成後,告訴Window Form的 Label控件Text屬性” Asynchronous End”.

Code1.1

 1

.Net的異步機制(線程間通信) - step 5

         delegate   void  DoWork();

 2

.Net的異步機制(線程間通信) - step 5

         private   void  button1_Click( object  sender, EventArgs e)

 3

.Net的異步機制(線程間通信) - step 5
.Net的異步機制(線程間通信) - step 5
.Net的異步機制(線程間通信) - step 5

{

 4

.Net的異步機制(線程間通信) - step 5

            //輔助方法,檢視目前線程

 5

.Net的異步機制(線程間通信) - step 5

            Debug.WriteLine(string.Format("Window Form Method.Thread ID:#{0}",

Thread.CurrentThread.ManagedThreadId));

 6

.Net的異步機制(線程間通信) - step 5

            //Label lblStatus 屬于主線程的控件[1]

 7

.Net的異步機制(線程間通信) - step 5

            this.lblStatus.Text = "Asynchronous Start.";

 8

.Net的異步機制(線程間通信) - step 5

            //使用委托來調用異步方法

 9

.Net的異步機制(線程間通信) - step 5

            DoWork work = DoWorkMethod;

10

.Net的異步機制(線程間通信) - step 5

            work.BeginInvoke(OnWorkCallback, work);

11

.Net的異步機制(線程間通信) - step 5

        }

12

.Net的異步機制(線程間通信) - step 5

         void  OnWorkCallback(IAsyncResult asyncResult)

13

.Net的異步機制(線程間通信) - step 5
.Net的異步機制(線程間通信) - step 5
.Net的異步機制(線程間通信) - step 5

{

14

.Net的異步機制(線程間通信) - step 5

            //輔助方法,檢視目前線程

15

.Net的異步機制(線程間通信) - step 5

            Debug.WriteLine(string.Format("Asynchronous Callback Method.Thread ID:#{0}",

Thread.CurrentThread.ManagedThreadId));

16

.Net的異步機制(線程間通信) - step 5

            DoWork work = asyncResult.AsyncState as DoWork;

17

.Net的異步機制(線程間通信) - step 5

            if (work != null)

18

.Net的異步機制(線程間通信) - step 5
.Net的異步機制(線程間通信) - step 5
.Net的異步機制(線程間通信) - step 5

{

19

.Net的異步機制(線程間通信) - step 5

                work.EndInvoke(asyncResult);

20

.Net的異步機制(線程間通信) - step 5

            }

21

.Net的異步機制(線程間通信) - step 5

            // 報錯:"線程間操作無效: 從不是建立控件“lblStatus”的線程通路它."

22

.Net的異步機制(線程間通信) - step 5

            this.lblStatus.Text = "Asynchronous End"; //上面注釋[1]

23

.Net的異步機制(線程間通信) - step 5

        }

24

.Net的異步機制(線程間通信) - step 5

25

.Net的異步機制(線程間通信) - step 5

         void  DoWorkMethod()

26

.Net的異步機制(線程間通信) - step 5
.Net的異步機制(線程間通信) - step 5
.Net的異步機制(線程間通信) - step 5

{

27

.Net的異步機制(線程間通信) - step 5

            Thread.Sleep(3000);//模拟耗時工作

28

.Net的異步機制(線程間通信) - step 5

        }

運作代碼,我們在第22行報錯(異步方法體内).為什麼呢?我們必須清楚的一點,在windows應用窗體應用程式中,對窗體上控件屬性的任何修改都必須在主線程中完成。不能從其他線程安全地通路控件的方法和屬性。從Debug視窗中我們也可以看出(圖1.1).執行Button Click事件的時候,運作線上程ID =#10; 在異步的方法體内,運作線上程ID=#7.不同線程間不能直接通信.

.Net的異步機制(線程間通信) - step 5

圖1.1

為了解決這個問題,實作圖1.1 中 #10 和 #7 的通信,下來開始認識

ISynchronizeInvoke

接口(此接口來自.Net Framework 1.0),提供3個方法1個屬性:

BeginInvoke / EndInvoke 方法 : 異步方法

Invoke 方法 : 同步方法

InvokeRequired 屬性 : 判讀來源的執行線程

下面我們看Code1.2的具體代碼來說明(對Code1.1改寫,其中Label 改為ListBox)

Code1.2

 1

.Net的異步機制(線程間通信) - step 5

         delegate   void  DoWork();

 2

.Net的異步機制(線程間通信) - step 5

         private   void  button1_Click( object  sender, EventArgs e)

 3

.Net的異步機制(線程間通信) - step 5
.Net的異步機制(線程間通信) - step 5
.Net的異步機制(線程間通信) - step 5

{

 4

.Net的異步機制(線程間通信) - step 5

            //更新狀态,添加到Listbox 中

 5

.Net的異步機制(線程間通信) - step 5

            AddValue("Asynchronous Start.");

 6

.Net的異步機制(線程間通信) - step 5

            //使用委托來調用異步方法

 7

.Net的異步機制(線程間通信) - step 5

            DoWork work = DoWorkMethod;

 8

.Net的異步機制(線程間通信) - step 5

            work.BeginInvoke(OnWorkCallback, work);

 9

.Net的異步機制(線程間通信) - step 5

        }

10

.Net的異步機制(線程間通信) - step 5

11

.Net的異步機制(線程間通信) - step 5

         void  OnWorkCallback(IAsyncResult asyncResult)

12

.Net的異步機制(線程間通信) - step 5
.Net的異步機制(線程間通信) - step 5
.Net的異步機制(線程間通信) - step 5

{

13

.Net的異步機制(線程間通信) - step 5

            DoWork work = asyncResult.AsyncState as DoWork;

14

.Net的異步機制(線程間通信) - step 5

            if (work != null)

15

.Net的異步機制(線程間通信) - step 5
.Net的異步機制(線程間通信) - step 5
.Net的異步機制(線程間通信) - step 5

{

16

.Net的異步機制(線程間通信) - step 5

                work.EndInvoke(asyncResult);

17

.Net的異步機制(線程間通信) - step 5

            }

18

.Net的異步機制(線程間通信) - step 5

            //(1)方法:調用Control控件的Invoke

19

.Net的異步機制(線程間通信) - step 5

            //Action<string> asyncUpdateState = UpdateStatus; //Action<string> 介紹=> 附1

20

.Net的異步機制(線程間通信) - step 5

            //Invoke(asyncUpdateState, "1:Asynchronous End.");

21

.Net的異步機制(線程間通信) - step 5

22

.Net的異步機制(線程間通信) - step 5

            //(2)方法:直接在異步調用的線程下

23

.Net的異步機制(線程間通信) - step 5

            UpdateStatus("2:Asynchronous End.");

24

.Net的異步機制(線程間通信) - step 5

        }

25

.Net的異步機制(線程間通信) - step 5

26

.Net的異步機制(線程間通信) - step 5

         void  UpdateStatus( string  input)

27

.Net的異步機制(線程間通信) - step 5
.Net的異步機制(線程間通信) - step 5
.Net的異步機制(線程間通信) - step 5

{

28

.Net的異步機制(線程間通信) - step 5

            //把你需要通知的控件Control 指派給ISynchronizeInvoke

29

.Net的異步機制(線程間通信) - step 5

            //來實作線程間的通信

30

.Net的異步機制(線程間通信) - step 5

            ISynchronizeInvoke async = this.listBoxStatus;

31

.Net的異步機制(線程間通信) - step 5

            //使用(1)方法,InvokeRequired == false ,來源目前(Window Form)主線程

32

.Net的異步機制(線程間通信) - step 5

            if (async.InvokeRequired == false)

33

.Net的異步機制(線程間通信) - step 5

                AddValue(input);

34

.Net的異步機制(線程間通信) - step 5

            else// 使用(2)方法 == true ,來源其他線程(異步)

35

.Net的異步機制(線程間通信) - step 5
.Net的異步機制(線程間通信) - step 5
.Net的異步機制(線程間通信) - step 5

{   

36

.Net的異步機制(線程間通信) - step 5

                Action<string> action = new Action<string>(status =>

37

.Net的異步機制(線程間通信) - step 5
.Net的異步機制(線程間通信) - step 5
.Net的異步機制(線程間通信) - step 5

{

38

.Net的異步機制(線程間通信) - step 5

                    AddValue(status);

39

.Net的異步機制(線程間通信) - step 5

                });

40

.Net的異步機制(線程間通信) - step 5

                //調用ISynchronizeInvoke 提供的Invoke 同步方法,阻礙線程,直到調用結束

41

.Net的異步機制(線程間通信) - step 5

                //也可以使用ISynchronizeInvoke 提供的異步BeginInvoke/EndInvoke方法來實作調用.

42

.Net的異步機制(線程間通信) - step 5
.Net的異步機制(線程間通信) - step 5

                async.Invoke(action, new object[] 

.Net的異步機制(線程間通信) - step 5

{ input });

43

.Net的異步機制(線程間通信) - step 5

            }

44

.Net的異步機制(線程間通信) - step 5

        }

45

.Net的異步機制(線程間通信) - step 5

46

.Net的異步機制(線程間通信) - step 5

         void  AddValue( string  input)

47

.Net的異步機制(線程間通信) - step 5
.Net的異步機制(線程間通信) - step 5
.Net的異步機制(線程間通信) - step 5

{

48

.Net的異步機制(線程間通信) - step 5

            this.listBoxStatus.Items.Add(string.Format("[(#{2}){0}]Context is null:{1}", input,Thread.CurrentContext==null, Thread.CurrentThread.ManagedThreadId));

49

.Net的異步機制(線程間通信) - step 5

        }

50

.Net的異步機制(線程間通信) - step 5

         void  DoWorkMethod()

51

.Net的異步機制(線程間通信) - step 5
.Net的異步機制(線程間通信) - step 5
.Net的異步機制(線程間通信) - step 5

{

52

.Net的異步機制(線程間通信) - step 5

            Thread.Sleep(3000);//模拟耗時工作

53

.Net的異步機制(線程間通信) - step 5

        }

.Net的異步機制(線程間通信) - step 5

圖1.2

在代碼中(UpdateStatus方法體内),我們可以看到主要是在ISynchronizeInvoke async = this.listBoxStatus;實作了線程間的通信,MSDN的解釋” 實作此接口的對象可以接收事件已發生的通知,并且可以響應有關該事件的查詢”. 并使Window Form(主線程) 下的ListBox 控件和來自異步方法(另外一個線程)的建立了通道. InvokeRequired 判斷線程的來源,如果使用(1)方法,來源于Window Form 自身Control 的Invoke方法, InvokeRequired将傳回false; 來源另外線程(異步)如果使用(2)傳回true.同時ISynchronizeInvoke 提供了異步(BeginInvoke+EndInvok)和同步方法(Invoke)來實作線程間通信.Invoke 就是最上面的圖1 所示的第一種 / BeginInvoke+EndInvok 是第二種.

附1:關于Action<T…> / Func (T…, TResult) (簡單的說就是”簡化後的委托”)的知識可以看MSDN的介紹.

Action<T…>: http://msdn.microsoft.com/zh-cn/library/018hxwa8.aspx

Func (T…, TResult): http://msdn.microsoft.com/zh-cn/library/bb549151.aspx

Code1.2雖然實作了線程間的通信, 回顧圖1的解釋,” 首先線程A 必須實作同步上下文對象(Synchronization Context)”, 而在Code1.2 中并沒有為Window Form(主線程)實作上下文對象,如果沒有這個對象一切都是不成立的.那麼Window Form 做了些什麼呢?

我們來看下面的代碼(使用Console程式):

Code1.3

 1

.Net的異步機制(線程間通信) - step 5

     static   class  Program

 2

.Net的異步機制(線程間通信) - step 5
.Net的異步機制(線程間通信) - step 5
.Net的異步機制(線程間通信) - step 5

{

 3

.Net的異步機制(線程間通信) - step 5

        static void Main()

 4

.Net的異步機制(線程間通信) - step 5
.Net的異步機制(線程間通信) - step 5
.Net的異步機制(線程間通信) - step 5

{

 5

.Net的異步機制(線程間通信) - step 5

            //1,在Main 主線程中運作,檢視線程ID和同步上下文

 6

.Net的異步機制(線程間通信) - step 5

            Console.WriteLine("0.ThreadID:#{1},Synchronization Context is null?{0}",

 7

.Net的異步機制(線程間通信) - step 5

                SynchronizationContext.Current == null, Thread.CurrentThread.ManagedThreadId);

 8

.Net的異步機制(線程間通信) - step 5

 9

.Net的異步機制(線程間通信) - step 5

            //2,在Main 主線程中運作,執行個體化空對象Test,檢視線程ID和同步上下文

10

.Net的異步機制(線程間通信) - step 5

            Test a = new Test();

11

.Net的異步機制(線程間通信) - step 5

            Console.WriteLine("1.ThreadID:#{1},Synchronization Context is null?{0}",

12

.Net的異步機制(線程間通信) - step 5

                SynchronizationContext.Current == null, Thread.CurrentThread.ManagedThreadId);

13

.Net的異步機制(線程間通信) - step 5

14

.Net的異步機制(線程間通信) - step 5

            //3,在Main 主線程中運作,執行個體化FormTest對象(繼承Form),檢視線程ID和同步上下文

15

.Net的異步機制(線程間通信) - step 5

            FormTest test = new FormTest();

16

.Net的異步機制(線程間通信) - step 5

            Console.WriteLine("2.ThreadID:#{1},Synchronization Context is null?{0}",

17

.Net的異步機制(線程間通信) - step 5

                SynchronizationContext.Current == null, Thread.CurrentThread.ManagedThreadId);

18

.Net的異步機制(線程間通信) - step 5

19

.Net的異步機制(線程間通信) - step 5

            //4,在新線程中運作,檢視線程ID和同步上下文

20

.Net的異步機制(線程間通信) - step 5

            new Thread(work).Start();

21

.Net的異步機制(線程間通信) - step 5

22

.Net的異步機制(線程間通信) - step 5

            Console.Read();

23

.Net的異步機制(線程間通信) - step 5

        }

24

.Net的異步機制(線程間通信) - step 5

        static void work()

25

.Net的異步機制(線程間通信) - step 5
.Net的異步機制(線程間通信) - step 5
.Net的異步機制(線程間通信) - step 5

{

26

.Net的異步機制(線程間通信) - step 5

            Console.WriteLine("3.ThreadID:#{1},Synchronization Context is null?{0}",

27

.Net的異步機制(線程間通信) - step 5

                SynchronizationContext.Current == null, Thread.CurrentThread.ManagedThreadId);

28

.Net的異步機制(線程間通信) - step 5

        }

29

.Net的異步機制(線程間通信) - step 5

    }

30

.Net的異步機制(線程間通信) - step 5
.Net的異步機制(線程間通信) - step 5

     public   class  FormTest : System.Windows.Forms.Form 

.Net的異步機制(線程間通信) - step 5

{ }

31

.Net的異步機制(線程間通信) - step 5
.Net的異步機制(線程間通信) - step 5

     public   class  Test 

.Net的異步機制(線程間通信) - step 5

{ }

.Net的異步機制(線程間通信) - step 5

圖1.3

由代碼和圖可以看出(SynchronizationContext.Current == null 判斷同步上下文對象是否存在), 執行個體化FormTest 對象後(繼承System.Windows.Forms.Form),Form預設的幫我們建立了同步上下文對象,使主線程#9 具備了同步上下文對象,這就是為什麼Code1.2 不用聲明同步上下文對象的原因,同時也告訴我們,開啟一個新線程#10,線程本身是沒有同步上下文對象的.

2.

SynchronizationContext 類

相比ISynchronizeInvoke 接口,SynchronizationContext 類(來自.Net Framework 2.0)提供了更多的方法來操作同步上下文對象,實作線程間通信.在上面的例子中SynchronizationContext類中将由 Post/Send 方法來實作.

反編譯後我們看到:

Code2.1

1

.Net的異步機制(線程間通信) - step 5

         public   virtual   void  Post(SendOrPostCallback d,  object  state)

2

.Net的異步機制(線程間通信) - step 5
.Net的異步機制(線程間通信) - step 5
.Net的異步機制(線程間通信) - step 5

{

3

.Net的異步機制(線程間通信) - step 5

            ThreadPool.QueueUserWorkItem(new WaitCallback(d.Invoke), state);

4

.Net的異步機制(線程間通信) - step 5

        }

5

.Net的異步機制(線程間通信) - step 5

6

.Net的異步機制(線程間通信) - step 5

         public   virtual   void  Send(SendOrPostCallback d,  object  state)

7

.Net的異步機制(線程間通信) - step 5
.Net的異步機制(線程間通信) - step 5
.Net的異步機制(線程間通信) - step 5

{

8

.Net的異步機制(線程間通信) - step 5

            d(state);

9

.Net的異步機制(線程間通信) - step 5

        }

Send = ISynchronizeInvoke 中的Invoke 同步調用.圖1中的第一種

Post = ISynchronizeInvoke 中的BeginInvoke + EndInvoke異步調用. 圖1中的第二種

改寫Code1.2的代碼(還是在WinForm 下程式設計).

Code2.2

 1

.Net的異步機制(線程間通信) - step 5

        delegate   void  DoWork();

 2

.Net的異步機制(線程間通信) - step 5

         private   void  button1_Click( object  sender, EventArgs e)

 3

.Net的異步機制(線程間通信) - step 5
.Net的異步機制(線程間通信) - step 5
.Net的異步機制(線程間通信) - step 5

{

 4

.Net的異步機制(線程間通信) - step 5

            //System.Windows.Forms.Form 自動的建立預設的同步上下文對象,

 5

.Net的異步機制(線程間通信) - step 5

            //直接的擷取目前的同步上下文對象

 6

.Net的異步機制(線程間通信) - step 5

            SynchronizationContext context = SynchronizationContext.Current;

 7

.Net的異步機制(線程間通信) - step 5

            //更新狀态,添加到Listbox 中

 8

.Net的異步機制(線程間通信) - step 5

            AddValue<string>("Asynchronous Start.");

 9

.Net的異步機制(線程間通信) - step 5

            //使用委托來調用異步方法

10

.Net的異步機制(線程間通信) - step 5

            DoWork work = DoWorkMethod;

11

.Net的異步機制(線程間通信) - step 5

            work.BeginInvoke(OnWorkCallback, context);

12

.Net的異步機制(線程間通信) - step 5

13

.Net的異步機制(線程間通信) - step 5

        }

14

.Net的異步機制(線程間通信) - step 5

         void  OnWorkCallback(IAsyncResult asyncResult)

15

.Net的異步機制(線程間通信) - step 5
.Net的異步機制(線程間通信) - step 5
.Net的異步機制(線程間通信) - step 5

{

16

.Net的異步機制(線程間通信) - step 5

            AsyncResult async = (AsyncResult)asyncResult;

17

.Net的異步機制(線程間通信) - step 5

            DoWork work = (DoWork)async.AsyncDelegate;

18

.Net的異步機制(線程間通信) - step 5

            work.EndInvoke(asyncResult);

19

.Net的異步機制(線程間通信) - step 5

20

.Net的異步機制(線程間通信) - step 5

            //更新狀态

21

.Net的異步機制(線程間通信) - step 5

            UpdateStatus("Asynchronous End.", asyncResult.AsyncState);

22

.Net的異步機制(線程間通信) - step 5

        }

23

.Net的異步機制(線程間通信) - step 5

         void  UpdateStatus( object  input, object  syncContext)

24

.Net的異步機制(線程間通信) - step 5
.Net的異步機制(線程間通信) - step 5
.Net的異步機制(線程間通信) - step 5

{

25

.Net的異步機制(線程間通信) - step 5

            //擷取主線程(Window Form)中同步上下文對象

26

.Net的異步機制(線程間通信) - step 5

            SynchronizationContext context = syncContext as SynchronizationContext;

27

.Net的異步機制(線程間通信) - step 5

            //使用SynchronizationContext 類中異步Post 方法

28

.Net的異步機制(線程間通信) - step 5
.Net的異步機制(線程間通信) - step 5

            SendOrPostCallback callback = new SendOrPostCallback(p => 

.Net的異步機制(線程間通信) - step 5

{

29

.Net的異步機制(線程間通信) - step 5

                AddValue<object>(p);

30

.Net的異步機制(線程間通信) - step 5

            });

31

.Net的異步機制(線程間通信) - step 5

            context.Post(callback, input);//Post 為異步,Send 為同步

32

.Net的異步機制(線程間通信) - step 5

33

.Net的異步機制(線程間通信) - step 5

        }

34

.Net的異步機制(線程間通信) - step 5

         void  AddValue < T > (T input)

35

.Net的異步機制(線程間通信) - step 5
.Net的異步機制(線程間通信) - step 5
.Net的異步機制(線程間通信) - step 5

{

36

.Net的異步機制(線程間通信) - step 5

            this.listBoxStatus.Items.Add(string.Format("[(#{2}){0}]Context is null:{1}", input, Thread.CurrentContext == null, Thread.CurrentThread.ManagedThreadId));

37

.Net的異步機制(線程間通信) - step 5

        }

38

.Net的異步機制(線程間通信) - step 5

         void  DoWorkMethod()

39

.Net的異步機制(線程間通信) - step 5
.Net的異步機制(線程間通信) - step 5
.Net的異步機制(線程間通信) - step 5

{

40

.Net的異步機制(線程間通信) - step 5

            Thread.Sleep(3000);//模拟耗時工作

41

.Net的異步機制(線程間通信) - step 5

        }

上面我們已經說過在主線程中System.Windows.Forms.Form 自動的建立預設的同步上下文對象, 這時候我們把目前的同步上下文對象通過參數的形式指派到異步線程中,調用Post 方法來實作, Post 方法接收 SendOrPostCallback 委托和額外object state參數,在Post方法體内調用線程池的線程來實作(Code2.1).當然我們也可以直接使用Send方法.

下面我們看看線程中的代碼(在Console 下程式設計).

Code2.3

 1

.Net的異步機制(線程間通信) - step 5

static   class  Program

 2

.Net的異步機制(線程間通信) - step 5
.Net的異步機制(線程間通信) - step 5
.Net的異步機制(線程間通信) - step 5

{

 3

.Net的異步機制(線程間通信) - step 5

        static void Main()

 4

.Net的異步機制(線程間通信) - step 5
.Net的異步機制(線程間通信) - step 5
.Net的異步機制(線程間通信) - step 5

{

 5

.Net的異步機制(線程間通信) - step 5

            Output("Main Thread Start.");

 6

.Net的異步機制(線程間通信) - step 5

            //為主線程建立Synchronization Context

 7

.Net的異步機制(線程間通信) - step 5

            var context = new SynchronizationContext();

 8

.Net的異步機制(線程間通信) - step 5

            //開始一個新線程

 9

.Net的異步機制(線程間通信) - step 5

            Thread threadB = new Thread(work);

10

.Net的異步機制(線程間通信) - step 5

            threadB.Start(context);

11

.Net的異步機制(線程間通信) - step 5

12

.Net的異步機制(線程間通信) - step 5

            Console.Read();

13

.Net的異步機制(線程間通信) - step 5

        }

14

.Net的異步機制(線程間通信) - step 5

        static void work(object context)

15

.Net的異步機制(線程間通信) - step 5
.Net的異步機制(線程間通信) - step 5
.Net的異步機制(線程間通信) - step 5

{

16

.Net的異步機制(線程間通信) - step 5

            Output("Thread B");

17

.Net的異步機制(線程間通信) - step 5

18

.Net的異步機制(線程間通信) - step 5

            //擷取主線程中的同步上下文對象

19

.Net的異步機制(線程間通信) - step 5

            SynchronizationContext sc = context as SynchronizationContext;

20

.Net的異步機制(線程間通信) - step 5

21

.Net的異步機制(線程間通信) - step 5

            //異步的方式和主線程通信,并發送"Hello World".

22

.Net的異步機制(線程間通信) - step 5

            sc.Post(new SendOrPostCallback(p =>

23

.Net的異步機制(線程間通信) - step 5
.Net的異步機制(線程間通信) - step 5
.Net的異步機制(線程間通信) - step 5

{

24

.Net的異步機制(線程間通信) - step 5

                Output(p);

25

.Net的異步機制(線程間通信) - step 5

            }), "Hello World");

26

.Net的異步機制(線程間通信) - step 5

        }

27

.Net的異步機制(線程間通信) - step 5

        static void Output(object value)

28

.Net的異步機制(線程間通信) - step 5
.Net的異步機制(線程間通信) - step 5
.Net的異步機制(線程間通信) - step 5

{

29

.Net的異步機制(線程間通信) - step 5

            Console.WriteLine("[ThreadID:#{0}]{1}", Thread.CurrentThread.ManagedThreadId, value);

30

.Net的異步機制(線程間通信) - step 5

        }

31

.Net的異步機制(線程間通信) - step 5

    }

.Net的異步機制(線程間通信) - step 5

圖2.3

在主線程中因為沒有同步上下文對象,是以開始我們new SynchronizationContext(); 對象,其他和Code2.2 基本一樣.從圖2.3很好的解釋圖1的第二種調用,也說明了Post 是開啟新線程(線程池)運作的.

3.

AsyncOperation / AsyncOperationManager 類

AsyncOperation / AsyncOperationManager 類是

SynchronizationContext 類的進一步封裝和實作, AsyncOperationManager在建立AsyncOperation對象的時候會取得目前線程的同步上下文對象,并存儲在AsyncOperation之中,使我們通路同步上下文對象更加容易.

Code3.1

 1

.Net的異步機制(線程間通信) - step 5

public   class  MySynchronizedClass

 2

.Net的異步機制(線程間通信) - step 5
.Net的異步機制(線程間通信) - step 5
.Net的異步機制(線程間通信) - step 5

{

 3

.Net的異步機制(線程間通信) - step 5

        private AsyncOperation operation;

 4

.Net的異步機制(線程間通信) - step 5

        public event EventHandler somethingHappened;

 5

.Net的異步機制(線程間通信) - step 5

        public MySynchronizedClass()

 6

.Net的異步機制(線程間通信) - step 5
.Net的異步機制(線程間通信) - step 5
.Net的異步機制(線程間通信) - step 5

{

 7

.Net的異步機制(線程間通信) - step 5

            //建立AsyncOperation 對象,并把目前線程的同步上下文保持到AsyncOperation中.

 8

.Net的異步機制(線程間通信) - step 5

            operation = AsyncOperationManager.CreateOperation(null);

 9

.Net的異步機制(線程間通信) - step 5

10

.Net的異步機制(線程間通信) - step 5

            Thread workerThread = new Thread(new ThreadStart(DoWork));

11

.Net的異步機制(線程間通信) - step 5

            workerThread.Start();

12

.Net的異步機制(線程間通信) - step 5

        }

13

.Net的異步機制(線程間通信) - step 5

14

.Net的異步機制(線程間通信) - step 5

        private void DoWork()

15

.Net的異步機制(線程間通信) - step 5
.Net的異步機制(線程間通信) - step 5
.Net的異步機制(線程間通信) - step 5

{

16

.Net的異步機制(線程間通信) - step 5

            SendOrPostCallback callback = new SendOrPostCallback(state =>

17

.Net的異步機制(線程間通信) - step 5
.Net的異步機制(線程間通信) - step 5
.Net的異步機制(線程間通信) - step 5

{

18

.Net的異步機制(線程間通信) - step 5

                  EventHandler handler = somethingHappened;

19

.Net的異步機制(線程間通信) - step 5

20

.Net的異步機制(線程間通信) - step 5

                  if (handler != null)

21

.Net的異步機制(線程間通信) - step 5
.Net的異步機制(線程間通信) - step 5
.Net的異步機制(線程間通信) - step 5

{

22

.Net的異步機制(線程間通信) - step 5

                      handler(this, EventArgs.Empty);

23

.Net的異步機制(線程間通信) - step 5

                  }

24

.Net的異步機制(線程間通信) - step 5

              });

25

.Net的異步機制(線程間通信) - step 5

26

.Net的異步機制(線程間通信) - step 5

            operation.Post(callback, null);

27

.Net的異步機制(線程間通信) - step 5

            //注意1

28

.Net的異步機制(線程間通信) - step 5

            operation.OperationCompleted();

29

.Net的異步機制(線程間通信) - step 5

        }

30

.Net的異步機制(線程間通信) - step 5

    }

代碼很簡單,我也不在解釋,可以參照上面所有代碼. 注意1:

AsyncOperation類中實作了

OperationCompleted的方法. SynchronizationContext 類中這個方法是沒有具體的代碼實作的.

總結:

文章中也非常适合線程的程式設計(除了異步)來實作通信, SynchronizationContext是最重要的一個,其他的擴充類,如SynchronizationContextSwitcher 等更進階的主題,具體可參考下面的連結. 在Winform中有個非常重要的

BackgroundWorker 類,關于

BackgroundWorker的文章很多,在此不做解釋了.

下一篇文章中,我将會讨論Web 上的異步方法.

技術參考:

http://www.codeproject.com/KB/cpp/SyncContextTutorial.aspx

http://www.codeproject.com/KB/threads/SynchronizationContext.aspx

http://www.codeproject.com/KB/threads/SynchronizationContext2.aspx

http://www.codeproject.com/KB/threads/SynchronizationContext3.aspx

http://www.code-magazine.com/Article.aspx?quickid=0403071

以上有word 文檔直接粘貼,排版可能不太好看,你可以通過下面來下載下傳相應的代碼/文檔

1,文檔

2,代碼(VS2008開發,.Net Framework 3.5(C Sharp)編寫)