對比以上的兩段程式碼,我們不難發現其中的差別,與上一段程式碼相比,我們在這裡使用了 BeginInvoke() 的另一個多載方法。其中的一個參數即為 BeginInvoke() 方法指定的回呼方法,在相應的目標方法執行完畢之後將呼叫該回呼方法,並且可以在相應的回呼用法中呼叫結束動作。
這裡值得順帶一提的是,有關我寫上一篇隨筆時留下的關於 Control.Invoke() 方法的疑問。
大家可能會發現,本節中提到的 [delegate].Invoke() 方法與上節中提到的 Control.Invoke() 方法在名稱書寫上是一樣的,那麼他們在功能上是否存在著些許的相似之處呢?以下是我做出的總結:
Return Work Thread
Control.Invoke 完成工作 強制於 UI Thread
Control.BeginInvoke 立即 強制於 UI Thread
[delegate].Invoke 完成工作 Call Invoke 的 Thread
[delegate].BeginInvoke 立即 新的背景 Thread
從中大家可以發現一個關鍵的問題,不論委派物件也好,Control 物件也好,他們的 Invoke() 方法都是以絕對同步的方式執行,而 BeginInvoke() 方法則是以絕對異步的方式執行。
在這裡,我之所以強調「絕對」兩個字,是為了提醒讀者雖然「異步」與「多執行緒」間存在著密切的聯繫,但異步並不等於在原程式的基礎上開設子執行緒,同步亦並非一定要針對單執行緒的程式而言。
我們不妨再以上一篇隨筆中「跨執行緒操控控制項」這段程式碼來說明問題,當然為說明問題方便,我做了部分調整:
using System.Threading;
namespace MulTrdDelegate
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
// 定義委派型別
public delegate void TreadDelgate();
// 初始化子執行緒物件
private Thread demoThread = null;
private void button1_Click(object sender, EventArgs e)
{
demoThread = new Thread(new ThreadStart(ThreadProcUnsafe));
demoThread.Start();
}
public void ThreadProcUnsafe()
{
if (this.textBox1.InvokeRequired)
{
TreadDelgate Objdelegate = new TreadDelgate(SetText);
this.Invoke(Objdelegate, new object[] {});
MessageBox.show("委派方法已返回!");
}
else
{
SetText();
}
}
private void SetText()
{
Thread.sleep(5000); // 人為延長方法的執行時間
string text = "這個控制項的內容是由子執行緒實現的";
this.textBox1.Text = text;
}
}
}
大家留心我在程式碼中用紅筆勾注的這句程式碼,如果說委派方法在呼叫時立即返回,那麼這句程式碼會馬上執行。不過,當大家執行時就會發現,這句程式碼是在 SetText() 方法返回之後才執行的——這便是 Control.Invoke() 方法所起到的作用了。大家注意,本身這是一個多執行緒程式,按理說 this.Invoke(Objdelegate, new object[] {}); 將相應的委派方法強制到主執行緒去執行,子執行緒是不受影響的,不過這裡卻是完全按照單執行緒的方式在執行的。這就是所謂的「絕對同步」,也就是說即使是多執行緒也同樣會強制按照單執行緒的方式來執行。這裡和本節提到的 [delegate].Invoke() 方法執行方式完全一致。
感興趣的讀者也可以嘗試將 this.Invoke() 改為 this.BeginInvoke(),查看一下執行效果。沒錯,和本節提到的 [delegate].BeginInvoke() 方法執行方式完全一致。
也就是說,不管當前執行的環境是多執行緒還是單執行緒。同步方法會強制程式按照單執行緒的方式執行,異步方法則強制程式按照多執行緒方式執行。
其實,從寫第一篇關於委派的隨筆開始,就不斷有園友問我:什麼時候採用委派?在這裡,我並不打算對這個問題做出正面回答。原因很簡單——程式效果是單一的,實現方式則是多種多樣的。這裡提供本人在學習委派過程中的幾個相當有代表性的實例,僅僅是為了幫助讀者們以自己的方式來理解委派的用途。每個人有每個人看待事物的獨特方式,別人的思想到你身上不一定就行得通。
真心希望以上的幾篇隨筆可以幫助讀者對委派有一個更深入的認識,屆時大家自然可以真真正正的總結出適合於自己思路的委派使用環境,以及,你自己眼中所看到的委派的真正面貌。