先來看一個“想當然”的代碼。
private void showDateTimeMethod() { while (true) { //顯示當前時間 label1.Text = "當前時間 " + DateTime.Now.ToString(); //線程暫停 Thread.Sleep(1000); } } private void Form1_Load(object sender, EventArgs e) { //新建一個線程 Thread showDateTimethread = new Thread(new ThreadStart(showDateTimeMethod)); //該線程為后台線程 showDateTimethread.IsBackground = true; //線程啟動 showDateTimethread.Start(); }
用我的大腿想想,上面的代碼應該是對的,但是由於net苛刻的安全機制,showDateTimeMethod中的代碼是有錯誤的。為了解決這個錯誤可以聲明一個委托類型,實例化一個委托變量(這話聽起來很拗口),並給這個委托變量指定函數引用。
方法一,使用命名方法
//聲明一個委托類型,該委托類型無輸入參數和輸出參數 public delegate void ProcessDelegate(); //函數引用,label控件顯示當前時間,輸入參數無,輸出參數無,和聲明的委托類型形式一致 public void LabelShow() { label1.Text = "當前時間 " + DateTime.Now.ToString(); }
然后在線程中實例化一個委托變量,指向這個函數引用。
while (true) { //使用命名方法 ProcessDelegate showProcess = new ProcessDelegate(LabelShow); //調用label的invoke方法 label1.Invoke(showProcess); //線程暫停 Thread.Sleep(1000); }
這樣的話就可以在窗體中看到當前的時間了。
方法二,使用匿名方法
剛剛的函數引用只有區區一行,這一行完全可以使用匿名方法實現,如果使用匿名方法的話就可以免去編寫一個函數,代碼顯得非常簡潔。
匿名方法使用方法也很簡單。
委托類型 委托變量 = delegate (【參數列表】){代碼塊};
while (true) { //實例化一個委托變量,使用匿名方法構造 ProcessDelegate showProcess = delegate() { label1.Text = "當前時間 " + DateTime.Now.ToString(); }; label1.Invoke(showProcess); //線程暫停 Thread.Sleep(1000); }
方法三,使用MethodInvoker
再觀察一下上面的代碼,這個委托類型,輸入參數無輸出參數也無,就可以使用C#的MethodInvoker直接構造,關於MethodInvoker,MSDN給出這樣一個解釋“表示一個委托,該委托可執行托管代碼中聲明為 void 且不接受任何參數的任何方法”
//使用匿名方法2 while (true) { label1.Invoke ( //委托,托管無參數的任何方法 new MethodInvoker ( delegate { label1.Text = "當前時間 " + DateTime.Now.ToString(); } ) ); //線程暫停 Thread.Sleep(1000); }