我也来玩玩WinForm~BeginInvoke让用户体验更好!

前言

先说明一下,本人不太做winform的项目,工作10年以来,一直奋斗在webform的舞台上,今天有机会也接触了一下winform,下面对工作中用到的BeginInvoke方法作一下说明,和大家也一起学习一下,呵呵。

BeginInvoke产生的原因

首先一个winform程序运行后,会有一个主线程(UI),我们看到的页面上的元素,表单,列表框等等都运行在主线程上的,主线程一阻塞,这些东西就都点不了了,呵呵,所以,在我们运行一些耗时的功能时,通常会开启一个新的线程去干这事,这是和乎情理的,想像一下,当我们在新线程里工作时,主线程不被阻塞(不假死),用户体验是多么好呀,当在新线程里干完事后,把消息返回给主线程,就OK了!

美中不足

想的挺好,可惜在新线程里,干完事后,运行程序,在为主窗体元素赋值时,出错了,说是不能访问主线程的元素,这到是正常的,线程与线程本来就是独立的,所以只能找其它方法了(可以使用这个方法解决上面的问题,但不推荐:  Control.CheckForIllegalCrossThreadCalls = false;)

BeginInvoke出来了

微软为了解决上面的线程之间信息相互访问的问题,封装了BeginInvoke方法,它允许我们传入一个委托,在委托方法中干这件时,这时你的主线程元素是可以被访问的,当处理完成后,可以操纵主线程的元素,即主线程元素重新赋值。

下面是一个简单的例子:

        /// <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();
        }

委托方法如下:

        /// <summary>
        /// 一个委托,把消息返回并填充到主窗体(主线程)的页面元素上
        /// </summary>
        /// <param name="month"></param>
        /// <returns></returns>
        private string InvodeGeneratorUserData(ReturnMsg res)
        {
            this.message.Text = res.GetDescription();//这里可以访问主线程的信息
            return res.GetDescription();
        }

下面是运行的效果图:

原文地址:https://www.cnblogs.com/lori/p/3214501.html