转:http://www.2cto.com/kf/201206/136587.html

在使用C#的过程中,难免会用到多线程,而用多线程之后,线程如何与界面交互则是一个非常头疼的问题。其实不仅仅是界面,一般情况下,我们往往需要获得线程的一些信息来确定线程的状态。比较好的方式是用委托实现,看例子:
         注:本例利用委托和跨线程访问技术,用界面上的两个label控件实时显示线程的执行次数。网上虽然有很多这方面的文章,但是过于简略,说明很少,刚刚接触这方面的程序员很难理解,故写此文。
 
TestClass类:

1. class TestClass 
2. { 
3.         //声明一个delegate(委托)类型:testDelegate,该类型可以搭载返回值为空,参数只有一个(long型)的方法。 
4.         public delegate void testDelegate(long i); 
5.  
6.         //声明一个testDelegate类型的对象。该对象代表了返回值为空,参数只有一个(long型)的方法。它可以搭载N个方法。 
7.         public testDelegate mainThread; 
8.  
9.         /// <summary> 
10.         /// 测试方法 
11.         /// </summary> 
12.         public void testFunction()  
13.         { 
14.             long i = 0; 
15.             while(true) 
16.             { 
17.                 i++; 
18.                 mainThread(i); //调用委托对象 
19.                 Thread.Sleep(1000);  //线程等待1000毫秒 
20.             } 
21.         } 
22. }

winform界面代码:

1. /// <summary> 
2. /// 按钮单击事件 
3. /// </summary> 
4. /// <param name="sender"></param> 
5. /// <param name="e"></param> 
6. private void button1_Click(object sender, EventArgs e) 
7. { 
8.     //创建TestClass类的对象 
9.     TestClass testclass = new TestClass(); 
10.  
11.     //在testclass对象的mainThread(委托)对象上搭载两个方法,在线程中调用mainThread对象时相当于调用了这两个方法。 
12.     testclass.mainThread = new TestClass.testDelegate(refreshLabMessage1); 
13.     testclass.mainThread += new TestClass.testDelegate(refreshLabMessage2); 
14.  
15.     //创建一个无参数的线程,这个线程执行TestClass类中的testFunction方法。 
16.     Thread testclassThread = new Thread(new ThreadStart(testclass.testFunction)); 
17.     //启动线程,启动之后线程才开始执行 
18.     testclassThread.Start(); 
19. } 
20.  
21. /// <summary> 
22. /// 在界面上更新线程执行次数 
23. /// </summary> 
24. /// <param name="i"></param> 
25. private void refreshLabMessage1(long i)  
26. { 
27.     //判断该方法是否被主线程调用,也就是创建labMessage1控件的线程,当控件的InvokeRequired属性为ture时,说明是被主线程以外的线程调用。如果不加判断,会造成异常 
28.     if (this.labMessage1.InvokeRequired) 
29.     { 
30.         //再次创建一个TestClass类的对象 
31.         TestClass testclass = new TestClass(); 
32.         //为新对象的mainThread对象搭载方法 
33.         testclass.mainThread = new TestClass.testDelegate(refreshLabMessage1); 
34.         //this指窗体,在这调用窗体的Invoke方法,也就是用窗体的创建线程来执行mainThread对象委托的方法,再加上需要的参数(i) 
35.         this.Invoke(testclass.mainThread,new object[] {i}); 
36.     } 
37.     else 
38.     { 
39.         labMessage1.Text = i.ToString(); 
40.     } 
41. } 
42.  
43. /// <summary> 
44. /// 在界面上更新线程执行次数 
45. /// </summary> 
46. /// <param name="i"></param> 
47. private void refreshLabMessage2(long i) 
48. { 
49.     //同上 
50.     if (this.labMessage2.InvokeRequired) 
51.     { 
52.         //再次创建一个TestClass类的对象 
53.         TestClass testclass = new TestClass(); 
54.         //为新对象的mainThread对象搭载方法 
55.         testclass.mainThread = new TestClass.testDelegate(refreshLabMessage2); 
56.         //this指窗体,在这调用窗体的Invoke方法,也就是用窗体的创建线程来执行mainThread对象委托的方法,再加上需要的参数(i) 
57.         this.Invoke(testclass.mainThread, new object[] { i }); 
58.     } 
59.     else 
60.     { 
61.         labMessage2.Text = i.ToString(); 
62.     } 
63. } 
执行效果:

说明:

为了便于大家理解,我写了很详细的注释。在这还要说明一下,因为这里边有些“莫名其妙”的地方。

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委托了两个方法,用+=运算符即可,如果想去除某个方法,亦可用-=运算符。www.2cto.com

l  最后需要说明的就是跨线程访问控件问题。窗体上的控件只允许创建它们的线程访问,也就是主线程,如果非主线程访问则会发生异常。我们可以借助于控件的InvokeRequired属性来判断该控件目前是否被主线程访问,如果是,返回false。如果不是,再利用Invoke方法找到主线程,让主线程执行访问控件的方法,本例中借助于TestClass类中的mainThread对象,委托了访问控件的方法refreshLabMessage1,再把mainThread对象传入运行在主线程上的控件的Invoke方法即可。Invoke方法可以理解为:在哪个控件上调用了Invoke,就用那个控件所在的线程处理委托方法。在本例中用this调用Invoke方法,也就是窗体所在的线程,当然也是控件所在的线程。Invoke的两个参数分别是:委托、委托的方法需要的参数。

转载于:https://www.cnblogs.com/tjy9999/p/4071533.html

C#利用委托跨线程更新UI数据相关推荐

  1. [转]C#利用委托跨线程更新UI数据

    在使用C#的过程中,难免会用到多线程,而用多线程之后,线程如何与界面交互则是一个非常头疼的问题.其实不仅仅是界面,一般情况下,我们往往需要获得线程的一些信息来确定线程的状态.比较好的方式是用委托实现, ...

  2. C# Winform 跨线程更新UI控件常用方法汇总(多线程访问UI控件)

    概述 C#Winform编程中,跨线程直接更新UI控件的做法是不正确的,会时常出现"线程间操作无效: 从不是创建控件的线程访问它"的异常.处理跨线程更新Winform UI控件常用 ...

  3. 简短总结一下C#里跨线程更新UI

    简短总结一下C#里跨线程更新UI 摘自: http://my.oschina.net/sdqxcxh/blog/53707 跨线程更新UI是写多线程程序尤其是通信类的程序经常遇到的问题,这里面主要的问 ...

  4. 简短总结一下C#里跨线程更新UI(转)

    摘自: http://my.oschina.net/sdqxcxh/blog/53707 跨线程更新UI是写多线程程序尤其是通信类的程序经常遇到的问题,这里面主要的问题是冲突,比如数据线程想要更新UI ...

  5. C# 委托 / 跨线程访问UI / 线程间操作无效: 从不是创建控件“Form1”的线程访问它...

    C# 委托 / 跨线程访问UI /  线程间操作无效: 从不是创建控件"Form1"的线程访问它 网上的代码都比较复杂,还是这个简单 见代码, 简易解决办法: 主窗体代码 usin ...

  6. 同步上下文(SynchronizationContext) 和 C#中跨线程更新UI的方法总结

    同步上下文(SynchronizationContext) 和 C#中跨线程更新UI的方法总结 在C#编程环境中,不允许在工作线程中直接对主线程(UI线程)中的控件进行更新操作.因此,稍微复杂一点的程 ...

  7. C#-WinForm跨线程修改UI界面

    背景 在我做WinForm开发的过程中,经常会遇到耗时操作或阻塞操作.他们会引发软件的卡顿甚至假死,严重影响软件的使用.因此,这类耗时或阻塞的操作一般都会使用异步的方式去执行,不影响主线程(UI线程) ...

  8. C#跨线程更新控件(UI)使用delegate方式

    C#跨线程更新(获取)控件(UI)使用delegate方式 在做界面开发的时候经常用到多线程,并且要在work线程中对控件或者界面进行操作,下面给出几种常用的操作方法 使用匿名委托到主线程中进行UI异 ...

  9. 经验证过的跨线程更新辅助类MyInvokeHelper

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...

  10. Android中Activity、Window、ViewRootImpl与子线程更新UI

    三者层级关系 1.Window Window是一个抽象类,唯一的实现类是PhoneWindow Window分为三种类型应用Window.子Window.系统Window.子Window无法独立存在必 ...

最新文章

  1. LeetCode简单题之有多少小于当前数字的数字
  2. docker mac python_Docker Python 例子
  3. Simulink仿真教程5---仿真参数设置和示波器的使用
  4. cf体验服_CF手游体验服_穿越火线枪战王者体验服申请_12月版本
  5. 使用ActiveMQ –具有故障转移协议的“主/从”配置
  6. 【CAA智库】宁滨院士:智能交通中的若干科学和技术问题
  7. java无序数组_Java查找不重复无序数组中是否存在两个数字的和为某个值
  8. Unsupported major.minor version 51.0 jdk版本错误解决方案 eclipse版
  9. .NET自动服务程序—C#
  10. 解决IDEA中Maven加载依赖包慢的问题
  11. 最有价值的编程忠告[转CSDN]
  12. 【华为云技术分享】从软件开发到 AI 领域工程师:模型训练篇
  13. 拼多多参谋:拼多多隐私号是什么意思?拼多多隐私号怎么查看真实号码?
  14. 怎么样才能彻底消灭猫瘟病毒?
  15. SAP文件上传服务器并下载
  16. 科技感十足五款APP软件,让你的手机不再低调!
  17. 什么是API Mock测试?
  18. 批量修改word中的公式--mathtype
  19. ElasticSearch(6.3.0)的配置和使用全过程
  20. 碧蓝航线内部表情包(有爱自取)

热门文章

  1. 【数据库系统原理】数据库设计
  2. Mysql短连接风暴
  3. kafka--Struct Streaming--hdfs案例
  4. Hbase预分区入门
  5. kafka事务操作案例演示
  6. Prometheus入门简介
  7. QT开发_弹出窗口禁用父窗口并移动到父窗口中心位置
  8. File类里的静态字段
  9. Unity Using Interception and Policy Injection
  10. 将Long类型的数通过UDP传输