先說明一下,本人不太作winform的項目,工做10年以來,一直奮鬥在webform的舞臺上,今天有機會也接觸了一下winform,下面對工做中用到的BeginInvoke方法做一下說明,和你們也一塊兒學習一下,呵呵。web
首先一個winform程序運行後,會有一個主線程(UI),咱們看到的頁面上的元素,表單,列表框等等都運行在主線程上的,主線程一阻塞,這些東西就都點不了了,呵呵,因此,在咱們運行一些耗時的功能時,一般會開啓一個新的線程去幹這事,這是和乎情理的,想像一下,當咱們在新線程裏工做時,主線程不被阻塞(不假死),用戶體驗是多麼好呀,當在新線程裏幹完過後,把消息返回給主線程,就OK了!學習
想的挺好,惋惜在新線程裏,幹完過後,運行程序,在爲主窗體元素賦值時,出錯了,說是不能訪問主線程的元素,這到是正常的,線程與線程原本就是獨立的,因此只能找其它方法了(能夠使用這個方法解決上面的問題,但不推薦: Control.CheckForIllegalCrossThreadCalls = false;)this
微軟爲了解決上面的線程之間信息相互訪問的問題,封裝了BeginInvoke方法,它容許咱們傳入一個委託,在委託方法中幹這件時,這時你的主線程元素是能夠被訪問的,當處理完成後,能夠操縱主線程的元素,即主線程元素從新賦值。spa
下面是一個簡單的例子:線程
/// <summary> /// 批量添加 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void button1_Click(object sender, EventArgs e) { message.Text = "程序正在處理..."; var beginInvokeThread = new Thread(() => { var result = userBll.GeneratorUserData(dateTimePicker1.Value);//耗時工做 #region BeginInvoke Func<ReturnMsg, string> funDelegate = new Func<ReturnMsg, string>(InvodeGeneratorUserData); IAsyncResult aResult = this.BeginInvoke(funDelegate, result); aResult.AsyncWaitHandle.WaitOne(-1); if (aResult.IsCompleted)//這裏不能夠訪問主線程的信息 MessageBox.Show(this.EndInvoke(aResult).ToString()); #endregion }); beginInvokeThread.Start(); }
委託方法以下:code
/// <summary> /// 一個委託,把消息返回並填充到主窗體(主線程)的頁面元素上 /// </summary> /// <param name="month"></param> /// <returns></returns> private string InvodeGeneratorUserData(ReturnMsg res) { this.message.Text = res.GetDescription();//這裏能夠訪問主線程的信息 return res.GetDescription(); }
下面是運行的效果圖:orm