线程间操作无效: 从不是创建控件“button1”的线程访问它。
.net2后是不能跨线程访问控件的。,窗体上的控件是当前线程创建的,当用户异步执行一个方法:在该方法中给窗体上的控件赋值,记住:当执行一个异步委托的时候,其实
就是开了一个线程去执行那个方法,这样就会报错:线程间操作无效: 从不是创建控件“某某某”的线程访问它。
C# WinForm开 发中,这是一个比较常见的异常:线程间操作无效,从不是创建控件“xxx”的线程访问它。这个异常来源于.NET2的一个限制:工作线程不能访问窗口线程 创建的控件。解决方法主要有两种,一种是在窗口线程中设置CheckForIllegalCrossThreadCalls = false ;另一种方式比较麻烦,使用委托的方式调用Invoke方法。
public Form1()
{
InitializeComponent();
Control.CheckForIllegalCrossThreadCalls = false;
}
但以上不是推荐的方法。更好的办法是用委托解决
private void button1_Click(object sender, EventArgs e)
{
new Action(show).BeginInvoke(null, null);
} void show()
{
//异步外的方法。这样窗体不会假死
while (true)
{
Thread.Sleep();
Action ac = new Action(showText);
this.Invoke(ac); //在同步方法里面实现更新窗体上的数据
}
} /// <summary>
/// 更新数据
/// </summary>
void showText()
{
richTextBox1.AppendText("更新\n");
}
或者使用InvokeRequired属性判断
/*
// 摘要:
// 获取一个值,该值指示调用方在对控件进行方法调用时是否必须调用 Invoke 方法,因为调用方位于创建控件所在的线程以外的线程中。
//
// 返回结果:
// 如果控件的 System.Windows.Forms.Control.Handle 是在与调用线程不同的线程上创建的(说明您必须通过 Invoke
// 方法对控件进行调用),则为 true;否则为 false。
private void button1_Click(object sender, EventArgs e)
{
//new Action(show).BeginInvoke(null, null);
new Action(show1).BeginInvoke(null, null);
}
void show1()
{
while (true)
{
Thread.Sleep();//模拟等待效果
show2();
}
} void show2()
{
//说明的当前外部线程
/*
// 摘要:
// 获取一个值,该值指示调用方在对控件进行方法调用时是否必须调用 Invoke 方法,因为调用方位于创建控件所在的线程以外的线程中。
//
// 返回结果:
// 如果控件的 System.Windows.Forms.Control.Handle 是在与调用线程不同的线程上创建的(说明您必须通过 Invoke
// 方法对控件进行调用),则为 true;否则为 false。
*/
if (InvokeRequired)
{
/*既然是外部线程,那么就没有权限访问主线程上的控件
* 故要主线程访问,开启一个异步委托捆绑要执行的方法
* 交给主线程执行
*/
Action ac = new Action(show2);
this.Invoke(ac); //这里执行后。则InvokeRequired就为false。因为此时已经是主线程访问当前创建的控件
}
else
{
richTextBox1.AppendText("更新77\n");
}
}
看了第一段代码是不是很不爽的感觉。showText()方法就一条赋值语句,则也独立成一个方法。这里可以简化代码,用匿名函数或者用更简单的lambda表达式(这个方法不需要其他用户调用,就可以考虑用匿名函数)。那么看简化后的代码
private void button1_Click(object sender, EventArgs e)
{
new Action(show).BeginInvoke(null, null);
} void show()
{
//异步外的方法。这样窗体不会假死
while (true)
{
Thread.Sleep();//在异步方法外实现等待,这样窗体不会假死
//Action ac = new Action(showText);
//this.Invoke(ac); //在同步方法里面实现更新窗体上的数据 //匿名函数
Action at = new Action(delegate(){ richTextBox1.AppendText("更新\n"); });
//lambda表达式更简单
Action at1 = new Action(()=> { richTextBox1.AppendText("更新\n"); });
this.Invoke(at); //这里this。代表当前窗体(控件)上的线程执行此方法
//这里不一定是this,只要是当前窗体上的控件都可以,比如
// button1.Invoke(at);
this.Invoke(at);//Invoke:在拥有此控件的基础窗口句柄的线程上执行指定的委托。
//richTextBox1.Invoke(at);
//button1.Invoke(at); }
}
我们用同样的方法把InvokeRequired属性判断的那段代码也用lambda表达式简写
private void button1_Click(object sender, EventArgs e)
{
new Action(show1).BeginInvoke(null, null);
}
void show1()
{
//while (true)
//{
// Thread.Sleep(2000);//模拟等待效果
// show2();
//} for (int i = ; i < ; i++)
{
Thread.Sleep();//模拟等待效果
//show2(); if (InvokeRequired)
{
Action ac = new Action(() => { richTextBox1.AppendText("更新767\n"); });
this.Invoke(ac); //这里执行后。则InvokeRequired就为false。因为此时已经是主线程访问当前创建的控件
}
} }
以上两种方法都是实现相同的效果,差别就是多了一个InvokeRequired判断是否需要执行Invoke()方法
参考:http://www.cnblogs.com/txw1958/archive/2012/08/21/2649192.html
线程间操作无效: 从不是创建控件“button1”的线程访问它。的更多相关文章
- 关于“线程间操作无效: 从不是创建控件’textBox1‘的线程访问它”异常的解决方法
线程间操作无效: 从不是创建控件“textBox1”的线程访问它 背景:通过一个辅助线程计算出的一个值赋给textBox1.text;解决办法:1.直接在窗体的构造函数中加:System.Window ...
- bug:C#线程间操作无效: 从不是创建控件" XX" 的线程访问它
今天遇到这个问题,百度了下,把解决的方法总结出来.我们在ui线程创建的子线程操作ui控件时,系统提示错误详细信息为:线程间操作无效: 从不是创建控件“XXX”的线程访问它. 就我知道的有三种方法,先看 ...
- 004. 线程间操作无效: 从不是创建控件“textBox1”的线程访问它
最简单的方法(不推荐): 在窗体构造函数中写Control.CheckForIllegalCrossThreadCalls =false; 为什么不推荐上面的方法: 为避免空间造成死锁, .net f ...
- (委托事件处理)关于多线程执行显示进度条的实例(转)&&线程间操作无效: 从不是创建控件“rtxtEntryNO”的线程访问它。
关于多线程执行显示进度条的实例! 之前回答了一篇关于怎么在线程中操作进度条的帖子,估计有人看的不是很明白今天没事,写了一个小小的实例,很简单,就2个文件权当抛砖引玉,希望有更好解决方案的人发表一下意见 ...
- 从.NET 1.1 升级到.NET 4.0 遇到 线程间操作无效: 从不是创建控件 [XX] 的线程访问它.
有两种方式解决 1.在窗体构造函数中写Control.CheckForIllegalCrossThreadCalls =false;2.使用Invoke等委托函数 问题原因是 .NET2.0 以后拒绝 ...
- System.InvalidOperationException:“线程间操作无效: 从不是创建控件“btnSearch”的线程访问它。
System.InvalidOperationException:“线程间操作无效: 从不是创建控件“btnSearch”的线程访问它.”这个问题属于跨线程问题 在Form1重载中写上一行代码 Sys ...
- System.InvalidOperationException:“线程间操作无效: 从不是创建控件“txtPortName02”的线程访问它。”
“System.InvalidOperationException”类型的未经处理的异常在 System.Windows.Forms.dll 中发生 其他信息: 线程间操作无效: 从不是创建控件“tx ...
- C#: 线程间操作无效: 从不是创建控件“dataGridView”的线程访问它
最近在修改自动化小工具,用多线程来解决后台拷贝导致WinForm界面卡死的情况,但是遇到过错:线程间操作无效: 从不是创建控件“dataGridView”的线程访问它. 这是因为在多线程程序中,新创建 ...
- 【转】线程间操作无效: 从不是创建控件“textBox2” 的线程访问它。
using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using Sy ...
随机推荐
- 更新快排中的partition
这一次是将partition 过程中, 维护三个区域. <x =x >x 三区域. 还有个待定的区域. /* * 将数组划分为三个分区, 小于arr[R], 等于arr[R], 大 ...
- 2012年蓝桥杯省赛A组c++第1题(xy迭代增殖)
/* 微生物增殖 题目: 假设有两种微生物 X 和 Y X出生后每隔3分钟分裂一次(数目加倍),Y出生后每隔2分钟分裂一次(数目加倍). 一个新出生的X,半分钟之后吃掉1个Y,并且,从此开始,每隔1分 ...
- WIN7环境变量path误删(windows找不到文件‘%windir%\systempropertiesadvanced.exe’)的解决办法
一.进入安全模式 1.通过Ctrl+R打开运行窗口,输入Msconfig 2.如上图,选择安全引导,点击确定.重启计算机进入安全模式. 二.在安全模式下,设置环境变量 1.C:\Windows\Sys ...
- 使用@import导入实现了ImportBeanDefinitionRegistrar接口的类,不能被注册为bean
今天在调试公司spring项目的时候发现了这样一个问题,由于我们的项目使用的是springboot就以springboot为例,代码如下: @Import({DataSourceRegister.cl ...
- 20165336 实验二 Java面向对象程序设计
20165336 实验二 Java面向对象程序设计 一.实验报告封面 课程:Java程序设计 班级:1653班 姓名:康志强 学号:20165336 指导教师:娄嘉鹏 实验日期:2018年4月16日 ...
- 第二章 构建布局良好的windows程序
工具箱→菜单和工具栏 菜单栏 MenuStrip的类型 MenuItem:菜单项 TextBox:文本框 ComboBoX:组合框 Separato:分割线 前面都有ToolStrip做前缀 Appl ...
- maven工程中防止mapper.xml文件被漏掉、未加载的方法
maven工程中防止mapper.xml文件被漏掉.未加载的方法 就是在pom.xml文件中添加以下内容 <!-- 如果不添加此节点mybatis的mapper.xml文件都会被漏掉. --&g ...
- (1.14)mysql锁问题之MyIsam
1.mysql锁概述 BDB被InnoDB代替了,MyIsam在8.0也被抛弃了 2.MyIsam表锁(读写是串行的) [2.1]查看表锁争用情况. MyIsam存储引擎只支持表锁. 查看表锁争用情况 ...
- Java基础知识(JAVA基本数据类型包装类)
基本数据类型的包装类 为什么需要包装类? Java并不是纯面向对象的语言.Java语言是一个面向对象的语言,但是Java的基本数据类型却不是面向对象的.但是我们在实际使用中经常需要将基本数据转化成对象 ...
- 初识Shell与Shell脚本
初识Shell Shell 是一个用 C 语言编写的程序,Shell 既是一种命令语言,又是一种程序设计语言. Shell 是指一种应用程序,这个应用程序提供了一个界面,用户通过这个界面访问操作系统内 ...