c#之如何安全的跨线程访问控件
2015-11-24 00:00
381 查看
摘要: 通过简单的demo来解决附加进程跨线程访问主线程控件问题
在窗体开发中用到线程是很常见的事情。比如一边下载东西一边点击其他功能。如果只有一个主线程。势必只会但同一时间处理一个功能,完了之后,才会去处理下一个功能。这样的体验,相比用一次,你就再也不想碰了。再比如,加入进度条控件的软件。进度条从0读取到100的过程中,是有一个while循环的。如果你放到主线程里面执行,那就呵呵了。在这个循环停止前,你会发现你的软件绝逼处于卡死状态。鼠标都拖不动它。为了解决这类问题。我们需要附加一个线程,相当于请一个助理,帮我们解决循环的事。这样我们的主线程才有闲工夫管理其他事。这样鼠标点击拖动窗体或者其他功能就不会受到影响。
好了,让我们一起,学习一下,怎么使用线程,以及附加的自定义线程如何安全的跨线程访问主线程中的控件。这里说明一下,所有的控件都属于主线程的,任何外来线程访问它,比如给它的属性赋值操作。都要采取安全的方式访问。这是软件开发的原则。那么现在我们先来看看,怎么做,才是线程访问不安全的呢?
请看代码:
以上就是不安全访问控件。如果你不加
运行是会报错的。编译器会对这种跨线程做安全检查。如果你这样直接访问,它是不允许的。所以必须禁用掉才可以的。当然咯,你禁用掉就可以正常运行了。但是这样不安全。做好不要这样使用咯。平时用的玩没关系。工作了这样用,显得很不专业咯。下面介绍安全的跨线程访问
很多网上这样写的。发现依然不行。虽然是创建了另外一个附加进程,但是它获取了主线程的控制权,尽管不会报错,倒是界面会卡死。
下面来看看正确的跨线程姿势:
第一种方式:
近两天会更新更多的方式。。。暂时写到这么多。楼主要睡觉了嘻嘻
在窗体开发中用到线程是很常见的事情。比如一边下载东西一边点击其他功能。如果只有一个主线程。势必只会但同一时间处理一个功能,完了之后,才会去处理下一个功能。这样的体验,相比用一次,你就再也不想碰了。再比如,加入进度条控件的软件。进度条从0读取到100的过程中,是有一个while循环的。如果你放到主线程里面执行,那就呵呵了。在这个循环停止前,你会发现你的软件绝逼处于卡死状态。鼠标都拖不动它。为了解决这类问题。我们需要附加一个线程,相当于请一个助理,帮我们解决循环的事。这样我们的主线程才有闲工夫管理其他事。这样鼠标点击拖动窗体或者其他功能就不会受到影响。
好了,让我们一起,学习一下,怎么使用线程,以及附加的自定义线程如何安全的跨线程访问主线程中的控件。这里说明一下,所有的控件都属于主线程的,任何外来线程访问它,比如给它的属性赋值操作。都要采取安全的方式访问。这是软件开发的原则。那么现在我们先来看看,怎么做,才是线程访问不安全的呢?
请看代码:
public Form1() { InitializeComponent(); Control.CheckForIllegalCrossThreadCalls = false;//禁止编译器对跨线程访问做检查,如果不加这一句,绝逼报错。不信你试试! } private void button1_Click(object sender, EventArgs e) { Thread thread1 = new Thread(new ParameterizedThreadStart(UpdateLabel)); thread1.Start("更新Label控件"); } private void UpdateLabel(object str) { this.label1.Text = str.ToString();//这个线程调用了主线程中的label1控件呵呵 }
以上就是不安全访问控件。如果你不加
Control.CheckForIllegalCrossThreadCalls = false;
运行是会报错的。编译器会对这种跨线程做安全检查。如果你这样直接访问,它是不允许的。所以必须禁用掉才可以的。当然咯,你禁用掉就可以正常运行了。但是这样不安全。做好不要这样使用咯。平时用的玩没关系。工作了这样用,显得很不专业咯。下面介绍安全的跨线程访问
很多网上这样写的。发现依然不行。虽然是创建了另外一个附加进程,但是它获取了主线程的控制权,尽管不会报错,倒是界面会卡死。
public partial class Form1 : Form { private delegate void FlushClient();//代理 public Form1() { InitializeComponent(); } private void Form1_Load(object sender, EventArgs e) { FlushClient fc=new FlushClient(ThreadFunction); fc.BeginInvoke(null,null);//使用begininvoke方法 } private void ThreadFunction() { while (true) { this.textBox1.Text = DateTime.Now.ToString(); Thread.Sleep(1000); } } }
下面来看看正确的跨线程姿势:
第一种方式:
delegate void done(); private Thread thread1 = null; private void Form1_Load(object sender, EventArgs e) { //thread1 = new Thread(new ThreadStart(counter)); thread1 = new Thread(new ThreadStart(crossthread)); thread1.IsBackground = true; thread1.Start(); } private void crossthread() { while (true) { Thread.Sleep(1000); dowork(); } } private void dowork() { if (this.txt_count.InvokeRequired) { done Done = new done(dowork); this.Invoke(Done); } else { this.txt_count.Text = DateTime.Now.ToString(); } }
近两天会更新更多的方式。。。暂时写到这么多。楼主要睡觉了嘻嘻
相关文章推荐
- C#将图片嵌入网页之中
- C#常量
- C# 中的委托和事件
- C#设计及其UML(反向工程)
- 【C#/算法】RGB、HSV、HSL颜色模型的互相转换
- C# 扩展方法
- C# 预处理器指令
- C#图表控件ZedGraph使用
- C# 多线程,论多核时代爱恨情仇
- c#多线程__Semaphore
- 【C#】——文件夹中获取指定特点的文件名
- C#写入文件的几种方式
- VS2015 新Web项目(C#6)出现CS1617错误的解决
- C# 移动无标题栏窗体的几种方法
- C#之猴子吃桃儿问题的解法——猴子吐桃儿
- C#文件的拆分与合并操作示例
- C#使用进度条,并用线程模拟真实数据 ProgressBar用法(转)
- c#中从string数组转换到int数组
- c#问答篇:对象与引用变量-----初学者的困惑
- C#读取本机IP