跨线程操作UI控件

写程序的时候经常会遇到跨线程访问控件的问题,看到不少人去设置Control.CheckForIllegalCrossThreadCalls = false;这句话是告诉编译器不要对跨线程访问作检查,可以实现访问,但是出不出错就不一定了。

个人建议使用委托delegate来实现。Windows中,UI是单线程的,即不允许多个线程直接访问它,通常它只由创建这个控件的线程(主线程)来控制,所以可以通过委托,告诉主线程对控件进行操作。

点击一个按钮,就创建一个线程添加一个item到ListView中,直接操作如下:

跨线程操作UI控件
//添加item
private
void AddItems() { this.listView1.Items.Add(new ListViewItem(new string[]{ Thread.CurrentThread.ManagedThreadId.ToString(), DateTime.Now.ToLongTimeString() })); }
跨线程操作UI控件

按钮事件

 private void button1_Click(object sender,EventArgs e)
       {
           Thread back_thread = new Thread(new ThreadStart(AddItems));
           back_thread.Start();
       }

运行,点击按钮,产生以下异常

跨线程操作UI控件

 

修改方式

声明一个委托

private delegate void addItemHandler(string ThreadID);

声明一个RunBackThread方法,它负责告诉主线程要干什么

跨线程操作UI控件
private void RunBackThread()
       {
           if (this.listView1.InvokeRequired)
           {
//声明一个AddItems的委托 addItemHandler add
= new addItemHandler(AddItems);
//this.Invoke(委托,请求线程ID参数)
this.Invoke(add,new object[]{Thread.CurrentThread.ManagedThreadId.ToString()}); } }
跨线程操作UI控件
this.Invoke的意思是在主线程上执行指定的委托,还有this.BeginInvoke在主线程上异步执行指定的委托。

按钮事件
private void button1_Click(object sender,EventArgs e)
       {
           Thread back_thread = new Thread(new ThreadStart(RunBackThread));
           back_thread.Start();
       }
AddItems方法和原来一样
跨线程操作UI控件
private void AddItems(string ThreadID)
       {
           this.listView1.Items.Add(new ListViewItem(new string[]{
               ThreadID,//请求线程ID
Thread.CurrentThread.ManagedThreadId.ToString(),//主线程ID DateTime.Now.ToLongTimeString() })); }
跨线程操作UI控件

这里之所以通过string ThreadID来获取请求线程id是因为AddItems这个方法是由主线程执行的,所以在AddItems方法里面通过Thread.CurrentThread.ManagedThreadId获取的id都是主线程id。

执行结果

跨线程操作UI控件

这个图看起来应该很容易明白了吧。



跨线程操作UI控件,布布扣,bubuko.com

跨线程操作UI控件

上一篇:使用python一步一步搭建微信公众平台(一)


下一篇:js的for in循环和java里的foreach循环的区别