C# invoke和beginInvoke

UI线程以外的线程不能直接更新UI界面,那如何在工作线程中更新UI界面呢?


invoke和beginInvoke的出现是为了解决跨线程更新UI显示的问题,invoke是同步的执行,而beginInvoke是异步执行的,不会阻塞后面的代码,但如果使用了endInvoke监听的话同样会阻塞后面代码,此时的作用相当于invoke。


此处以一个10秒走表例子来说明问题


一、阻塞UI线程方法

        private void button1_Click(object sender, EventArgs e)
        {
            for (int i = 1; i <=10;i++)
            {
                 Thread.Sleep(1000);
                 lblSecond.Text = i.ToString();//主线程会卡死
            }
        }


二、创建新线程执行任务,并用control.Invoke更新UI显示

        private void button2_Click(object sender, EventArgs e)
        {
            Thread myThread = new Thread(new ThreadStart(ShowSecond));
            myThread.Start();
        }

        private delegate void showSecondDelegate();//定义一个委托

        private void ShowSecond()
        {
            for (int i = 1; i <= 10; i++)
            {
                Thread.Sleep(1000);
                this.Invoke(new showSecondDelegate(delegate() //在委托方法中更新UI控件值
                {
                    lblSecond.Text = i.ToString(); //如果将thread.sleep放到此处,则会阻塞主线程,因为此处运行在主线程上
                }));
                //后面的代码    //后面的代码会等invoke委托方法执行完成后再执行
                //...
             }
        }

三、创建新线程执行任务,并用control.BeginInvoke更新UI显示

        private void button3_Click(object sender, EventArgs e)
        {
            Thread myThread = new Thread(ShowSecond1);
            myThread.Start();
        }

        private delegate void showSecondDelegate1(); 
        private void ShowSecond1()
        {
            for (int i = 1; i <= 10; i++)
            {

                this.BeginInvoke(new showSecondDelegate1(delegate()
                {
                    MessageBox.Show(i.ToString());
                    lblSecond.Text = i.ToString();
                }));
                //后面的代码     //后面的代码会立即执行,不会等BeginInvoke委托方法执行完成后再执行
                //...                               
            }            
        }

四、创建新线程执行任务,并用control.BeginInvoke更新UI显示,使用control.EndInvoke监听结果,并阻塞当前线程
       private delegate bool showSecondDelegate2(); 
        /// <summary>
        /// 异步(beginInvoke更新UI-阻塞工作线程)
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button4_Click(object sender, EventArgs e)
        {
            Thread myThread = new Thread(ShowSecond2);
            myThread.Start();
            
        }

        private void ShowSecond2()
        {
            for (int i = 1; i <= 10; i++)
            {
                Thread.Sleep(1000);
                IAsyncResult iasync = this.BeginInvoke(new showSecondDelegate2(delegate()
                {
                    lblSecond.Text = i.ToString();
                    return true;
                }));
                object result = this.EndInvoke(iasync);  //监听BeginInvoke委托方法执行结果,阻塞后面代码执行,直到委托方法执行完成               
                //后面的代码
                //...
        }    }


 

总结:


1、invoke和beginInvoke委托方法依然运行在主线程中,而不是当前线程,使用thread.sleep照样会阻塞主线程,所以耗时的操作应该放在工作线程中执行,更新UI显示

      相关的代码放在委托方法中

2、在工作线程中想异步更新UI界面显示的话用beginInvoke,不影响后面代码运行

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值