使用Invoke解决多线程间的控件访问出错
// 按钮点击事件处理程序
private void button1_Click(object sender, EventArgs e)
{
//创建新线程
Thread processorThread = null;
processorThread = new Thread(new ThreadStart(Done));
processorThread.IsBackground = true;
processorThread.SetApartmentState(ApartmentState.STA);
processorThread.Start();
}
// 定义委托
delegate void WriteInvoke(string msg);
private void Write(string msg)
{
textBox1.Text = msg;
}
// 更新textBox1值
private void Done()
{
this.Invoke(new WriteInvoke(Write), new object[] { "www.mzwu.com" });
}
Invoke方法会顺着控件树向上搜索,直到找到创建控件的那个线程(通常是主线程),
然后进入那个线程改变控件的外观,确保不发生线程冲突
之前写的:
public void SetMyTextBox(string str, TextBox abc)
{
if (abc.InvokeRequired)
{//如果控件的 Handle 是在与调用线程不同的线程上创建的
//(说明您必须通过 Invoke 方法对控件进行调用),则为 true;否则为 false。
SetMyTextbox_F d = new SetMyTextbox_F(SetMyTextBox);
// Me.Invoke(d, New Object() {str, abc})
this.Invoke(d, new object[] { str,abc });
//this.Invoke(new InvokeDelegate(InvokeMethod));
}
else {
int myLength;
//myLength = System.Text.Encoding.Default.GetByteCount(abc.Text);
//If myLength >= 32000 Then abc.text = ""
//if (myLength >= 3200){
// abc.Text = "";
//}
abc.Text = abc.Text + str;
}
}
C#中禁止跨线程直接访问控件,InvokeRequired是为了解决这个问题而产生的,当一个控件的InvokeRequired属性值为真时,说明有一个创建它以外的线程想访问它。
获取一个值,该值指示调用方在对控件进行方法调用时是否必须调用 Invoke 方法,因为调用方位于创建控件所在的线程以外的线程中。
如果控件的 Handle 是在与调用线程不同的线程上创建的(说明您必须通过 Invoke 方法对控件进行调用),则为 true;否则为 false。
Windows 窗体中的控件被绑定到特定的线程,不具备线程安全性 。因此,如果从另一个线程调用控件的方法,那么必须使用控件的一个 Invoke 方法来将调用封送到适当的线程。该属性可用于确定是否必须调用 Invoke 方法,当不知道什么线程拥有控件时这很有用。
获取一个值,该值指示调用方在对控件进行方法调用时是否必须调用 Invoke 方法,因为调用方位于创建控件所在的线程以外的线程中。
如果控件的 Handle 是在与调用线程不同的线程上创建的(说明您必须通过 Invoke 方法对控件进行调用),则为 true;否则为 false。
Windows 窗体中的控件被绑定到特定的线程,不具备线程安全性 。因此,如果从另一个线程调用控件的方法,那么必须使用控件的一个 Invoke 方法来将调用封送到适当的线程。该属性可用于确定是否必须调用 Invoke 方法,当不知道什么线程拥有控件时这很有用。
------------------------------------------------------------------------
首先定义一个委托,与这个事件处理函数的签名一样委托,当然直接使用该事件的委托也是可以的,如:
private delegate void InvokeCallback( string msg);
然后就是判断这个属性的值来决定是否要调用Invoke函数:
void m_comm_MessageEvent( string msg)
{
if (txtMessage.InvokeRequired)
{
InvokeCallbackmsgCallback = new InvokeCallback(m_comm_MessageEvent);
txtMessage.Invoke(msgCallback, new object [] { msg } );
}
else
{
txtMessage.Text = msg;
}
}
说明:这个函数就是事件处理函数,txtMessage是一个文本框。
这样就做到了窗体中控件的线程安全性。
------------------------------------------------------------------------
InvokeRequired 当前线程不是创建控件的线程时为true
比如你可以自己开一个Thread,或使用Timer的事件来访问窗体上的控件的时候,在线程中窗体的这个属性就是True的。
简单的说,如果有两个线程,Thread A和Thread B,并且有一个Control c,是在Thread A里面new的。
那么在Thread A里面运行的任何方法调用c.InvokeRequired都会返回false。
相反,如果在Thread B里面运行的任何方法调用c.InvokeRequired都会返回true。
是否是UI线程与结果无关。(通常Control所在的线程是UI线程,但是可以有例外)
也可以认为,在new Control()的时候,control用一个变量记录下了当前线程,在调用InvokeRequired时,返回当前线程是否不等于new的时候记录下来的那个线程。
Control..::.Invoke ---> 在拥有此控件的基础窗口句柄的线程上执行委托。
Control..::.BeginInvoke ---> 在创建控件的基础句柄所在线程上异步执行委托。
Invoke() 调用时,会阻塞当前线程,等到 Invoke() 方法返回才继续执行后面的代码,表现出“同步”的概念。
BeginInvoke() 调用时,当前线程会启用线程池中的某个线程来执行此方法,当前线程不被阻塞,继续运行后面的代码,表现出“异步”的概念。
EndInvoke() ,在想获取 BeginInvoke() 执行完毕后的结果时,调用此方法来获取。
部分来自于:http://blog.163.com/wangzhenguo2005@126/blog/static/3714052620101995557981/写的很详细
使用Invoke解决多线程间的控件访问出错的更多相关文章
- C#多线程操作界面控件的解决方案(转)
C#中利用委托实现多线程跨线程操作 - 张小鱼 2010-10-22 08:38 在使用VS2005的时候,如果你从非创建这个控件的线程中访问这个控件或者操作这个控件的话就会抛出这个异常.这是微软为了 ...
- C# LIstbox 解决WinForm下ListBox控件“设置DataSource属性后无法修改项集合”的问题
解决WinForm下ListBox控件“设置DataSource属性后无法修改项集合”的问题 分类: winform2008-05-24 02:33 2592人阅读 评论(11) 收藏 举报 winf ...
- 解决WinForm下ListBox控件“设置DataSource属性后无法修改项集合”
解决WinForm下ListBox控件“设置DataSource属性后无法修改项集合” 最近更新: 2013-2-15 587 很少写WinForm程序第一次使用ListBox控件就遇到了比 ...
- vs设计界面出现“建控件时出错 响应在此上下文中不可用”
使用VS2010设计Asp.net时出现: 只有在配置文件或 Page 指令中将 enableSessionState 设置为 true 时,才能使用会话状态.还请确保在应用程序配置的 \\ 节中包括 ...
- 使用TaskScheduler 调度器 实现跨线程的控件访问
//任务调度器 TaskScheduler UIscheduler = null; public Form1() { //获取任务调度器 UIscheduler = TaskScheduler.Fro ...
- c#多线程(UI线程,控件显示更新) Invoke和BeginInvoke 区别
如果只是直接使用子线程访问UI控件,直接看内容三,如果想深入了解从内容一看起. 一.Control.Invoke和BeginInvoke方法的区别 先上总结: Control.Invoke 方法 (D ...
- [转] c#多线程(UI线程,控件显示更新) Invoke和BeginInvoke 区别
如果只是直接使用子线程访问UI控件,直接看内容三,如果想深入了解从内容一看起. 一.Control.Invoke和BeginInvoke方法的区别 先上总结: Control.Invoke 方法 (D ...
- 富客户端 wpf, Winform 多线程更新UI控件
前言 在富客户端的app中,如果在主线程中运行一些长时间的任务,那么应用程序的UI就不能正常相应.因为主线程要负责消息循环,相应鼠标等事件还有展现UI. 因此我们可以开启一个线程来格外处理需要长时间的 ...
- 常量,字段,构造方法 调试 ms 源代码 一个C#二维码图片识别的Demo 近期ASP.NET问题汇总及对应的解决办法 c# chart控件柱状图,改变柱子宽度 使用C#创建Windows服务 C#服务端判断客户端socket是否已断开的方法 线程 线程池 Task .NET 单元测试的利剑——模拟框架Moq
常量,字段,构造方法 常量 1.什么是常量 常量是值从不变化的符号,在编译之前值就必须确定.编译后,常量值会保存到程序集元数据中.所以,常量必须是编译器识别的基元类型的常量,如:Boolean ...
随机推荐
- 变量对象、作用域链和This
变量对象 作用域链 This 整理自:https://www.cnblogs.com/TomXu/archive/2011/12/15/2288411.html 系列文章中变量对象,作用域链和this ...
- Json学习总结(1)——Java和JavaScript中使用Json方法大全
摘要:JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式.它基于ECMAScript的一个子集. JSON采用完全独立于语言的文本格式,但是也使用了类似于C语 ...
- spark系统实现yarn资源的自动调度
参考: http://blog.csdn.net/dandykang/article/details/48160953 对于Spark应用来说,资源是影响Spark应用执行效率的一个重要因素. ...
- Android自己定义视图(一):带下划线的TextView
package com.francis.underlinetextviewtest; import android.content.Context; import android.content.re ...
- h5播放音乐
h5音频播放,里面參数能够查看http://www.w3school.com.cn/html5/html_5_audio.asp <audio controls="controls&q ...
- Linux-----Ubuntu Server安装图形界面
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/ ...
- poweroff---关闭计算机操作系统并且切断系统电源。
poweroff命令用来关闭计算机操作系统并且切断系统电源. 语法 poweroff(选项) 选项 -n:关闭操作系统时不执行sync操作: -w:不真正关闭操作系统,仅在日志文件“/var/log/ ...
- WPF MVVM架构 EF、WCF、IOC 设计示例经典
概要 该演示项目利用WPF应用程序构建的MVVM架构示例, 运用了Unity容器接口注入, MVVM的经典设计, 后台利用的EF+WCF. 后台实现: 从数据库生成的emdx 结合上下文进行数据交互, ...
- Java语言的Hook实现
引言:最近在玩完美时空的诛仙Online(不知道这里有没人有共同爱好的),这个游戏每晚七点会出现一个任务"新科试炼".这个任务简单地说就是做选择题,范围小到柴米油盐,大到世界大千, ...
- gdal读写图像分块处理
转自赵文原文 gdal读写图像分块处理(精华版) Review: 用gdal,感觉还不如直接用C++底层函数对遥感数据进行处理.因为gdal进行太多封装,如果你仅仅只是Geotif等格式进行处理,IO ...