C#利用委托跨线程更新UI数据
来源:互联网 发布:大数据笔试题目 编辑:程序博客网 时间:2024/06/05 15:04
点击打开链接
在使用C#的过程中,难免会用到多线程,而用多线程之后,线程如何与界面交互则是一个非常头疼的问题。其实不仅仅是界面,一般情况下,我们往往需要获得线程的一些信息来确定线程的状态。比较好的方式是用委托实现,看例子:
注:本例利用委托和跨线程访问技术,用界面上的两个label控件实时显示线程的执行次数。网上虽然有很多这方面的文章,但是过于简略,说明很少,刚刚接触这方面的程序员很难理解,故写此文。
TestClass类:
- class TestClass
- {
- //声明一个delegate(委托)类型:testDelegate,该类型可以搭载返回值为空,参数只有一个(long型)的方法。
- public delegate void testDelegate(long i);
- //声明一个testDelegate类型的对象。该对象代表了返回值为空,参数只有一个(long型)的方法。它可以搭载N个方法。
- public testDelegate mainThread;
- /// <summary>
- /// 测试方法
- /// </summary>
- public void testFunction()
- {
- long i = 0;
- while(true)
- {
- i++;
- mainThread(i); //调用委托对象
- Thread.Sleep(1000); //线程等待1000毫秒
- }
- }
- }
winform界面代码:
- /// <summary>
- /// 按钮单击事件
- /// </summary>
- /// <param name="sender"></param>
- /// <param name="e"></param>
- private void button1_Click(object sender, EventArgs e)
- {
- //创建TestClass类的对象
- TestClass testclass = new TestClass();
- //在testclass对象的mainThread(委托)对象上搭载两个方法,在线程中调用mainThread对象时相当于调用了这两个方法。
- testclass.mainThread = new TestClass.testDelegate(refreshLabMessage1);
- testclass.mainThread += new TestClass.testDelegate(refreshLabMessage2);
- //创建一个无参数的线程,这个线程执行TestClass类中的testFunction方法。
- Thread testclassThread = new Thread(new ThreadStart(testclass.testFunction));
- //启动线程,启动之后线程才开始执行
- testclassThread.Start();
- }
- /// <summary>
- /// 在界面上更新线程执行次数
- /// </summary>
- /// <param name="i"></param>
- private void refreshLabMessage1(long i)
- {
- //判断该方法是否被主线程调用,也就是创建labMessage1控件的线程,当控件的InvokeRequired属性为ture时,说明是被主线程以外的线程调用。如果不加判断,会造成异常
- if (this.labMessage1.InvokeRequired)
- {
- //再次创建一个TestClass类的对象
- TestClass testclass = new TestClass();
- //为新对象的mainThread对象搭载方法
- testclass.mainThread = new TestClass.testDelegate(refreshLabMessage1);
- //this指窗体,在这调用窗体的Invoke方法,也就是用窗体的创建线程来执行mainThread对象委托的方法,再加上需要的参数(i)
- this.Invoke(testclass.mainThread,new object[] {i});
- }
- else
- {
- labMessage1.Text = i.ToString();
- }
- }
- /// <summary>
- /// 在界面上更新线程执行次数
- /// </summary>
- /// <param name="i"></param>
- private void refreshLabMessage2(long i)
- {
- //同上
- if (this.labMessage2.InvokeRequired)
- {
- //再次创建一个TestClass类的对象
- TestClass testclass = new TestClass();
- //为新对象的mainThread对象搭载方法
- testclass.mainThread = new TestClass.testDelegate(refreshLabMessage2);
- //this指窗体,在这调用窗体的Invoke方法,也就是用窗体的创建线程来执行mainThread对象委托的方法,再加上需要的参数(i)
- this.Invoke(testclass.mainThread, new object[] { i });
- }
- else
- {
- labMessage2.Text = i.ToString();
- }
- }
执行效果:
说明:
为了便于大家理解,我写了很详细的注释。在这还要说明一下,因为这里边有些“莫名其妙”的地方。
l 如何创建线程就不废话了,一看就懂。
l public delegate void testDelegate(long i);这句话是创建了一个委托,名字是testDelegate,指定了委托的类型,什么返回值啦、什么参数啦,可以把testDelegate理解为一个类,一个规范;publictestDelegate mainThread;这句话当然就是创建testDelegate类的对象了,真正搭载方法的是mainThread对象,它可以搭载N个方法,顺序执行。如何搭载捏?看这句话:testclass.mainThread= new TestClass.testDelegate(refreshLabMessage1);这句话是给testclass对象中的mainThread对象搭载方法,但是后边的new比较难以理解。大家都知道,new这个关键字就是用来创建对象的,刚刚已经提醒大家把委托看成一个类,因此这new的是testDelegate这个委托,而不是TestClass(一定要看清了,如果是new的TestClass,要在TestClass后加括号的,后边接的是方法,而testDelegate明显不是方法,因此会报错)。相当于是在TestClass类中又套了一个类,所以才会这样写。refreshLabMessage1当然就是testDelegate类构造方法的参数,用来指明委托哪个方法。最后把实例赋给同类型的mainThread。另外,在此例中mainThread委托了两个方法,用+=运算符即可,如果想去除某个方法,亦可用-=运算符。
l 最后需要说明的就是跨线程访问控件问题。窗体上的控件只允许创建它们的线程访问,也就是主线程,如果非主线程访问则会发生异常。我们可以借助于控件的InvokeRequired属性来判断该控件目前是否被主线程访问,如果是,返回false。如果不是,再利用Invoke方法找到主线程,让主线程执行访问控件的方法,本例中借助于TestClass类中的mainThread对象,委托了访问控件的方法refreshLabMessage1,再把mainThread对象传入运行在主线程上的控件的Invoke方法即可。Invoke方法可以理解为:在哪个控件上调用了Invoke,就用那个控件所在的线程处理委托方法。在本例中用this调用Invoke方法,也就是窗体所在的线程,当然也是控件所在的线程。Invoke的两个参数分别是:委托、委托的方法需要的参数。
- C#利用委托跨线程更新UI数据
- C#利用委托跨线程更新UI数据
- C#利用委托跨线程更新UI数据
- c#利用委托跨线程调用UI控件完整使用方法
- C# 异步线程加载数据 更新UI
- C# 委托实现跨线程更新控件
- C# 线程更新 UI
- 线程更新UI (线程与委托)
- c#利用委托进行异步跨线程加载到窗体数据
- C#中跨线程更新UI
- [教程]C#委托多线程更新UI
- C# Winform使用线程,委托定时更新界面UI控件,解决界面卡顿问题
- C# 通过线程更新UI
- c# 线程中更新UI
- C# 线程向UI通信 委托(delegate)
- C#中利用委托实现多线程跨线程操作
- C#中利用委托实现多线程跨线程操作
- C#中利用委托实现多线程跨线程操作
- C#多线程与UI响应
- 【足迹C++primer】39、动态内存与智能指针(2)
- Python学习笔记之特点
- HDU 4403 A very hard Aoshu problem (DFS暴力)
- 01背包-动态规划
- C#利用委托跨线程更新UI数据
- strcpy和memcpy的区别
- hdu 4442 Physical Examination
- 第一次项目——流程图
- C++:在堆上创建对象,还是在栈上?
- 图的连通性问题专题整理
- struts2比struts1好在哪里?
- asp.net服务器控件添加属性
- 浅谈C#多线程与UI响应