关闭

C# invoke和beginInvoke

标签: c#invokebeginInvoke
506人阅读 评论(0) 收藏 举报
分类:

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,不影响后面代码运行

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:168618次
    • 积分:2138
    • 等级:
    • 排名:第18469名
    • 原创:51篇
    • 转载:60篇
    • 译文:0篇
    • 评论:25条
    最新评论