我也來玩玩WinForm~BeginInvoke讓用戶體驗更好!

前言

先說明一下,本人不太作winform的項目,工做10年以來,一直奮鬥在webform的舞臺上,今天有機會也接觸了一下winform,下面對工做中用到的BeginInvoke方法做一下說明,和你們也一塊兒學習一下,呵呵。web

BeginInvoke產生的緣由

首先一個winform程序運行後,會有一個主線程(UI),咱們看到的頁面上的元素,表單,列表框等等都運行在主線程上的,主線程一阻塞,這些東西就都點不了了,呵呵,因此,在咱們運行一些耗時的功能時,一般會開啓一個新的線程去幹這事,這是和乎情理的,想像一下,當咱們在新線程裏工做時,主線程不被阻塞(不假死),用戶體驗是多麼好呀,當在新線程裏幹完過後,把消息返回給主線程,就OK了!學習

美中不足

想的挺好,惋惜在新線程裏,幹完過後,運行程序,在爲主窗體元素賦值時,出錯了,說是不能訪問主線程的元素,這到是正常的,線程與線程原本就是獨立的,因此只能找其它方法了(能夠使用這個方法解決上面的問題,但不推薦:  Control.CheckForIllegalCrossThreadCalls = false;)this

BeginInvoke出來了

微軟爲了解決上面的線程之間信息相互訪問的問題,封裝了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

相關文章
相關標籤/搜索