1 using System; 2 using System.Collections.Generic; 3 using System.ComponentModel; 4 using System.Data; 5 using System.Drawing; 6 using System.Linq; 7 using System.Text; 8 using System.Windows.Forms; 9 using System.Threading; 10 11 namespace InvokeTest 12 { 13 public partial class Form1 : Form 14 { 15 public Form1() { 16 InitializeComponent(); 17 } 18 19 /** 20 * 對 委托 的 BeginInvoke,EndInvoke 及 Control 的 BeginInvoke,EndInvoke 的理解: 21 * 22 * 委托的 BeginInvoke,是使用 異步的方式. 它的參數1 是傳入一個完成方法后調用的回調函數 23 * 參數2,是像 這個回調函數里傳入的一個 Object 參數. 24 * 25 * EndInvoke ,是得到 委托方法的返回值. 如果委托方法沒有返回值.那就只需要一個用來完成 26 * 后回調的方法即可. 如果有返回值的方法. 還是很有必要使用這個 EndInvoke 的. 27 * 28 * Control 上的 Invoke 及 BeginInvoke 都是運行在 UI 線程上的,所以都會造成 界面阻塞. 29 * 我們一般是使用委托的 BeginInvoke 去異步執行一些耗時方法.在 執行完后 的回調中使用 30 * Control.Invoke 方法去更新UI界面 如: 31 * this.Invoke(new Action(() => this.button1.Text = (string)ar.AsyncState)); 32 */ 33 34 // 如果調用 BeginInvoke 的方法沒有返回值的話,只是在方法結束后調用一個 回調函數的話 35 // 則在 BeginInvoke 的時候就不必傳入委托自身. 當然也不需要調用 EndInvoke 方法,得到 36 // 返回值了. 37 private void Form1_Load(object sender, EventArgs e) { 38 // 異步 39 (new Action(() => { Thread.Sleep(3000); })).BeginInvoke(new AsyncCallback((ar) => { 40 this.Invoke(new Action(() => this.button1.Text = (string)ar.AsyncState)); 41 }), "KAOKAO"); 42 } 43 44 45 // 如果你調用 BeginInvoke 的委托方法是有返回值的,那么你就需要在調用BeginInvoke的時候,把 46 // 委托的本身做為第二個參數傳到 CallBack 函數中,在里面 通過 把 AsyncState 強轉為我們的委托 47 // 類型, 然后就可以使用委托的 EndInvoke 方法,這個方法返回的就是 我們的委托函數所返回的值. 48 private void button1_Click(object sender, EventArgs e) { 49 // Func 50 Func<float> Func = new Func<float>(() => { Thread.Sleep(1000); return 123.456f; }); 51 52 Func.BeginInvoke(new AsyncCallback((ar) => { 53 Func<float> tmp = (Func<float>)ar.AsyncState; 54 float tmpint = tmp.EndInvoke(ar); 55 this.Invoke(new Action(() => { 56 this.label1.Text = tmpint.ToString(); 57 })); 58 }), Func); 59 } 60 } 61 }