using System; using System.Threading; using System.Collections.Generic; using System.Windows.Forms; namespace AsyncDemo { public partial class Form1 : Form { public Form1() { InitializeComponent(); } class objstate //申明一個實體類 { public string fname; public string lname; public DateTime birthday; public objstate() { fname = "wang"; lname = "nima"; birthday = DateTime.Now; } public objstate(string fn, string ln) { fname = fn; lname = ln; //birthday = DateTime.Now; } } AsyncCallback callback; objstate obj; #region easy demo //申明委託 public delegate string deltest(); deltest begin; private void button1_Click(object sender, EventArgs e) { begin = new deltest(method); callback = new AsyncCallback(back); obj = new objstate();//實例化類,該對象能夠傳入回調函數中 begin.BeginInvoke(back, obj);//異步執行method,界面不會假死,5秒後執行回調函數,彈出提示框 } private void back(IAsyncResult ar) { string res = begin.EndInvoke(ar); objstate obj = (objstate)(ar.AsyncState);//經過AsyncState獲取傳入的object MessageBox.Show(res + "\n" + obj.fname + " " + obj.lname + " " + obj.birthday); } private string method() { Thread.Sleep(5000); return "welcome to this world"; } #endregion #region complex demo //申明委託 public delegate void deltest1(); deltest1 begin1; public delegate string deltest2(List<string> list); deltest2 begin2; private void button2_Click(object sender, EventArgs e) { string id = Thread.CurrentThread.ManagedThreadId.ToString(); Thread.CurrentThread.Name = "MainThread"; richTextBox1.Text = "主線程線程ID:" + id + " 主線程名:" + Thread.CurrentThread.Name + "\n"; begin1 = new deltest1(method1); callback = new AsyncCallback(back1); List<objstate> list = new List<objstate>(); for (int i = 0; i < 10; i++) { objstate obj = new objstate("James" + (i * i).ToString(), "Warke" + (i * 3).ToString()); list.Add(obj); } //delegate.BeginInvoke(parameter[] para, AsyncCallback callback, object obj) //para是method方法的參數; //callback是method方法執行完後在同一子線程中當即執行的回調函數; //obj是一個能夠傳入回調函數中的object ,在回調函數中經過 IAsyncResult.AsyncState獲取 begin1.BeginInvoke(back1, list); this.Location = new System.Drawing.Point(0, 0); MessageBox.Show("主線程沒有阻塞"); } private void back1(IAsyncResult ar) { begin1.EndInvoke(ar); //回調函數中的線程ID與異步執行method時的線程ID相同,說明說明回調函數也是在子線程中執行 string id = Thread.CurrentThread.ManagedThreadId.ToString(); if (this.IsHandleCreated) { IAsyncResult iar = this.BeginInvoke(new Action(delegate() { richTextBox1.Text += "正在調用back函數 " + "當前線程ID:" + id + "\n"; })); this.EndInvoke(iar); } List<objstate> list = (List<objstate>)(ar.AsyncState);//經過AsyncState獲取傳入的object List<string> strList = new List<string>(); for (int i = 0; i < 10; i++) { Thread.Sleep(3000); //winform中控件的屬性設置或操做只能有主線程進行 //所以在子線程中須要調用 Control.BeginInvoke(Delegate method)方法 在主線程上對控件進行操做 //Control.BeginInvoke中傳入的方法,應儘可能只包含對控件操做的語句,這樣主線程可以快速執行完對控件的操做,主界面不會假死 //Action<T>()是無返回值的泛型委託 Func<T>()是帶返回值的泛型委託 //線程的執行有可能在窗口句柄建立完成前進行,此時會報錯,所以 子線程中要異步操做主線程中的控件就須要在主線程的窗口句柄建立完成後進行 //句柄的類型是 IntPtr ,至關於windows中的身份證, 是一個指向指針的指針, 在內存中有固定的地址 //指針指向一塊內存引用類或方法或程序集,不過內存中的地址會不斷改變,系統須要經過一個指向指針的指針來記載數據地址的變動,即是句柄 if (this.IsHandleCreated) { IAsyncResult iar = this.BeginInvoke(new Action(delegate() { richTextBox1.Text += "正在調用back函數 " + "當前線程ID:" + id + " 正在給第" + (i + 1).ToString() + "我的賦值" + "\n"; })); this.EndInvoke(iar); } DateTime now = DateTime.Now; list[i].birthday = now; string str = now.ToLongTimeString() + " " + list[i].fname + "." + list[i].lname; strList.Add(str); } begin2 = new deltest2(method2); begin2.BeginInvoke(strList, back2, null); } private void back2(IAsyncResult ar) { //有返回值的方法,能夠經過EndInvoke(IAsyncResult ar)方法獲取返回值 string res = begin2.EndInvoke(ar); //回調函數中的線程ID與異步執行method時的線程ID相同,說明說明回調函數也是在子線程中執行 string id = Thread.CurrentThread.ManagedThreadId.ToString(); if (this.IsHandleCreated) { IAsyncResult iar = this.BeginInvoke(new Action(delegate() { richTextBox1.Text += "正在調用back2函數 " + "當前線程ID:" + id + "\n"; })); this.EndInvoke(iar); } MessageBox.Show(res); } private void method1() { string id = Thread.CurrentThread.ManagedThreadId.ToString(); for (int i = 5; i > 0; i--) { Thread.Sleep(1000); if (this.IsHandleCreated) { IAsyncResult iar = this.BeginInvoke(new Action(delegate() { richTextBox1.Text += "正在調用method方法 " + "當前線程ID:" + id + " " + i.ToString() + "秒後method方法,進入回調函數\n"; })); this.EndInvoke(iar); } } } private string method2(List<string> list) { string id = Thread.CurrentThread.ManagedThreadId.ToString(); for (int i = 0; i < 10; i++) { Thread.Sleep(3000); if (this.IsHandleCreated) { IAsyncResult iar = this.BeginInvoke(new Action(delegate() { richTextBox1.Text += "正在調用method2方法 " + "當前線程ID:" + id + "\n"; richTextBox1.Text += list[i] + "\n"; richTextBox1.Select(richTextBox1.TextLength, 0); })); this.EndInvoke(iar); } } return "finish"; } #endregion } }