c#子线程调用主线程控件
2015-10-19 10:23
609 查看
相信对多线程有所了解的人都知道,子线程是不能直接操作winform上的控件的,因为默认的控件是在主线程上生成的,子线程是不能直接访问或者修改的,直接访问或者修改控件属性的话会报错。这个即使在Java上也是这样,Android中也经常被用到的。
这样的话,子线程岂不是没办法访问主线程生成的控件了,当然是否定的,有问题就用解决办法,微软的人更了解这一点,并且有好几种解决办法,主要的思路就是在子线程里,使用delegate代理一个主线程里面的方法。直接看代码:
这样写的话,毫无疑问会报错,就是咱们上面说到的情况,子线程直接操作ui元素。我们对这个进行改造一下:
然后在线程中实例化一个委托变量,指向这个函数引用。
这样的话就能执行成功了。在这里showDateTimethread.IsBackground = true;必须要加上。不知道大家注意没有,如果子线程里有 死循环(有时间必须用循环)或子线程在进行一个阻塞式的操作,如影响队列里的消息,那么不能主线程用什么方式终止子线程都没门,
this.thread.Suspend();
this.thread.Abort()
通通不管用,Abort() 方法也只是建议子线程终止,而不是无条件强行终目,这个不好,比如应用程序要退出,子线程结束不了会一直驻留内存exe都不会退出进程,有什么办法强行终止子线程哈,不要说类似于(不要用死循环,无意义之类的话,那对阻塞式的操作怎么说呢)
这一句的时候把线程阻死了 System.Messaging.Message m = q.Receive();
不管等多少,线程都是死的。
可以试试在退出的时候用
System.Environment.Exit(System.Environment.ExitCode);
Application.Exit();
还用在那些线程开始前,使用它的属性IsBackground,把它设为true,这样在你程序结束的时候,线程也会自动结束。
大家都知道随着linq和ef的流行,一个新的概念出现了,而且目前比较流行,那就是lambda,匿名函数,大家都知道,匿名函数可以用委托进行操作,可以说他是委托初始化的一种新的,便捷的形式,同样的道理,传统的委托必须得声明一个新的方法,才能使用委托,但是匿名函数,可以省去重新声明一个函数,直接看代码:
这样一来的话,简单明了,省去很多代码。
这样的话,子线程岂不是没办法访问主线程生成的控件了,当然是否定的,有问题就用解决办法,微软的人更了解这一点,并且有好几种解决办法,主要的思路就是在子线程里,使用delegate代理一个主线程里面的方法。直接看代码:
private void showDateTimeMethod() { while (true) { //显示当前时间 label1.Text = "当前时间 " + DateTime.Now.ToString(); //线程暂停 Thread.Sleep(1000); } } private void Form1_Load(object sender, EventArgs e) { //新建一个线程 Thread showDateTimethread = new Thread(new ThreadStart(showDateTimeMethod)); //该线程为后台线程 showDateTimethread.IsBackground = true; //线程启动 showDateTimethread.Start(); }
这样写的话,毫无疑问会报错,就是咱们上面说到的情况,子线程直接操作ui元素。我们对这个进行改造一下:
//声明一个委托类型,该委托类型无输入参数和输出参数 public delegate void ProcessDelegate(); //函数引用,label控件显示当前时间,输入参数无,输出参数无,和声明的委托类型形式一致 public void LabelShow() { label1.Text = "当前时间 " + DateTime.Now.ToString(); }
然后在线程中实例化一个委托变量,指向这个函数引用。
while (true) { //使用命名方法 ProcessDelegate showProcess = new ProcessDelegate(LabelShow); //调用label的invoke方法 label1.Invoke(showProcess); //线程暂停 Thread.Sleep(1000); }
这样的话就能执行成功了。在这里showDateTimethread.IsBackground = true;必须要加上。不知道大家注意没有,如果子线程里有 死循环(有时间必须用循环)或子线程在进行一个阻塞式的操作,如影响队列里的消息,那么不能主线程用什么方式终止子线程都没门,
this.thread.Suspend();
this.thread.Abort()
通通不管用,Abort() 方法也只是建议子线程终止,而不是无条件强行终目,这个不好,比如应用程序要退出,子线程结束不了会一直驻留内存exe都不会退出进程,有什么办法强行终止子线程哈,不要说类似于(不要用死循环,无意义之类的话,那对阻塞式的操作怎么说呢)
这一句的时候把线程阻死了 System.Messaging.Message m = q.Receive();
不管等多少,线程都是死的。
可以试试在退出的时候用
System.Environment.Exit(System.Environment.ExitCode);
Application.Exit();
还用在那些线程开始前,使用它的属性IsBackground,把它设为true,这样在你程序结束的时候,线程也会自动结束。
大家都知道随着linq和ef的流行,一个新的概念出现了,而且目前比较流行,那就是lambda,匿名函数,大家都知道,匿名函数可以用委托进行操作,可以说他是委托初始化的一种新的,便捷的形式,同样的道理,传统的委托必须得声明一个新的方法,才能使用委托,但是匿名函数,可以省去重新声明一个函数,直接看代码:
while (true) { //实例化一个委托变量,使用匿名方法构造 ProcessDelegate showProcess = delegate() { label1.Text = "当前时间 " + DateTime.Now.ToString(); }; label1.Invoke(showProcess); //线程暂停 Thread.Sleep(1000); }
这样一来的话,简单明了,省去很多代码。
相关文章推荐
- AX2009 C#客户端通过Web service批量审核工作流(一)
- (原创)c#学习笔记03--变量和表达式04--表达式04--命名空间
- 猴子选大王——CSharp数组
- C#面向对象设计模式纵横谈——3.Abstract Factory 抽象工厂(创建型模式)
- C#读写(OFFICE 2013)excel表格(续)
- (原创)c#学习笔记03--变量和表达式04--表达式03--运算符的优先级
- C#运算符重载和索引器
- (原创)c#学习笔记03--变量和表达式04--表达式02--赋值运算符
- (原创)c#学习笔记03--变量和表达式04--表达式01--数学运算符
- c# 输出一个数组
- c# 窗体编程注意事项
- C# 6.0 (C# vNext) 的新功能:Exception-Handling Improvements
- C#读写(OFFICE 2013)excel表格
- C#中的readonly
- C#学习日记25---匿名方法 与 Func委托 与 lambda表达式
- C#验证类 可验证:邮箱,电话,手机,数字,英文,日期,身份证,邮编,网址,IP (转)
- C#属性
- C#创建COM组件
- C#学习之操作excel表格
- c# WinForm 中英文智能提示