C# invoke和beginInvoke

来源:互联网 发布:mac 中文乱码 编辑:程序博客网 时间:2024/06/05 04:48

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
原创粉丝点击