c#中对"Cross-thread operation not valid"错误的处理办法

概要

Windows Forms 控件通常不是thread-safe(直接或间接继承于System.Windows.Forms.Control),因此.NET Framework为防止multithread下对控件的存取可能导致控件状态的不一致,在调试时,CLR-Debugger会抛出一个InvalidOperationException以‘建议‘程序员程序可能存在的风险。

问题的关键在于,动机是什么?和由此而来的编程模型的调整。

1. Example

首先,看一个代码实例。该例要完成的工作是由一个Button的Click触发,启动一个Thread(Manual Thread),该Thread的目的是完成设置TextBox的Text’s Property。

1.1 Unsafe access to control

Code 1.1

using System;

using System.Configuration;

using System.Collections.Generic;

using System.ComponentModel;

using System.Data;

using System.Drawing;

using System.Text;

using System.Windows.Forms;

using System.Threading;

using System.IO;

namespace WindowsApplication1 {

public partial class Form1 : Form {

public Form1() {

InitializeComponent();

}

private void unsafeSetTextButton_Click(object sender, EventArgs e) {

Thread setTextThread = new Thread(new ThreadStart(doWork));

setTextThread.Start();

}

private void doWork() {

string fileName = ".\\test-src.txt";

if (!File.Exists(fileName)) {

MessageBox.Show(string.Format("{0} doesn‘t exist!", fileName),

"FileNoFoundException");

return;

}

string text = null;

using (StreamReader reader = new StreamReader(fileName, Encoding.Default)) {

text = reader.ReadToEnd();

}

this.textBox1.Text = text;

}

}

}

在调试时,CLR-Debugger会在以上代码中粗体处将会弹出如下的对话框:

提示说,当前存取控件的thread非创建控件的thread(Main Thread)。

1.2 What’s mean?

当然,你也可以忽略InvalidOperationException,在非调试的状态下,该异常并不会被抛出,CLR-Debugger监测对Handle的可能存在的不一致地存取,而期望达到更稳健(robust)的代码,这也就是Cross-thread operation not valid后的真正动机。

但是,放在面前的选择有二:第一,在某些情况下,我们并不需要这种善意的‘建议‘,而这种建议将在调试时带来了不必要的麻烦;第二,顺应善意的‘建议‘,这也意味着我们必须调整已往行之有效且得心应手的编程模型(成本之一),而这种调整额外还会带来side-effect,而这种side-effect目前,我并不知道有什么简洁优雅的解决之道予以消除(成本之二)。

2. The first choice : CheckForIllegalCrossThreadCalls

忽略Cross-thread InvalidOperationException建议,前提假设是我们不需要类似的建议,同时也不想给自己的调试带来过多的麻烦。

关闭CheckForIllegalCrossThreadCalls,这是Control class上的一个static property,默认值为flase,目的在于开关是否对Handle的可能存在的不一致存取的监测;且该项设置是具有Application scope的。

如果,只需要在某些Form中消除Cross-thread InvalidOperationException建议,可以在Form的.ctor中,InitializeComponent语句后将CheckForIllegalCrossThreadCalls设置为false 。

Code 2. - 1

public Form1() {

InitializeComponent();

Control.CheckForIllegalCrossThreadCalls = false;

}

c#中对"Cross-thread operation not valid"错误的处理办法

时间: 2025-01-05 03:17:30

c#中对"Cross-thread operation not valid"错误的处理办法的相关文章

linux 编译中required file `./ltmain.sh' not found 错误的解决办法(转)

在linux下编译c/c++程序出错:$ automake --add-missing....configure.in:18: required file `build/ltmain.sh' not found .... -------------------------------------------------------- 解决方案(libtoolize配置即可): $libtoolize --version-libtoolize (GNU libtool) 1.4.2.....$li

C# Cross thread operation detected.

最近改别人的代码调试时报这个错,调试了蛮久没发现什么问题,百度了下也没发现相应的解决方案. Thread th = new Thread(new ThreadStart(() => { table.Rows.Clear(); checkSaveData(); BindDataGrid(table); })); th.IsBackground = true; th.Start(); 后来经过别人解释才想到大概是什么原因.报错提示的大致意思就是在线程里面操作窗体的控件,当时没发现什么代码在什么地方调

线程中的current thread not owner异常错误

多线程常用的一些方法: wait(),wait(long),notify(),notifyAll()等 这些方法是当前类的实例方法, wait()      是使持有对象锁的线程释放锁;wait(long)是使持有对象锁的线程释放锁时间为long(毫秒)后,再次获得锁,wait()和wait(0)等价;notify()    是唤醒一个正在等待该对象锁的线程,如果等待的线程不止一个,那么被唤醒的线程由jvm确定;notifyAll 是唤醒所有正在等待该对象锁的线程. 并且应该优先使用notify

virtualbox 中的linux 共享文件 发生文件系统类型错误的解决办法

转自:http://blog.csdn.net/ls1160/article/details/24913391 最近在研究linux下的安卓源代码编译,遇到了一些问题,在虚拟机的共享文件上. 因为联网下载安卓源代码太慢了,如果按照老罗的方法的话,于是就自己离线下载了包,打算直接共享到linux虚拟机里面使用. 在实验室直接共享就可以了,但是编译的话,由于linux是32位的,产生了一些错误不知道怎么解决了.于是就想着换到64位,但是,这个时候共享文件就出了问题. 后面查资料还是解决了. [网上的

AspNet Mvc 路由解析中添加.html 等后缀 出现404错误的解决办法

使用Mvc 有时候我们希望,浏览地址以.html .htm 等后缀名进行结尾. 于是我们就在RouteConfig 中修改路由配置信息,修改后的代码如下 routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); routes.MapRoute( name: "Default", url: "{controller}/{action}.html", defaults: new { controller =

VMWare 12虚拟机启动过程中提示“虚拟设备ide0:1无法连接”错误的解决办法

在VMWare 12上装好系统之后,正常地关闭.过了一天再次启动虚拟系统的时候,却提示"虚拟设备ide0:1无法连接"的错误,上网搜索一下并无找到具体的解决办法.强制关闭虚拟系统后,到虚拟机配置界面,找到CD/DVD配置一栏,将"启动时连接"前面的钩去掉即可解决此问题.之所以会出现这个问题是由于宿主主机并没有CD/DVD这个物理设备,所以如果钩选了"启动时连接"的话,系统会因为找不到真实的设备而报"虚拟设备ide0:1无法连接"

C# AE开发 报错 没有注册类 检索 COM 类工厂中 CLSID 为 { } 的组件时失败 错误的解决办法

原因很可能是没有添加对AE使用的许可!!! 两种方法添加 1.可以手动添加控件到窗体上.(这种方式添加的许可,PoJie版可能到开发后期会闪退.) 2.代码方式添加许可.   参考:https://www.cnblogs.com/aegisada/p/3924292.html 原文地址:https://www.cnblogs.com/tigerK/p/11978427.html

【转发】Cross-thread operation not valid: Control 'progressBar1' accessed from a thread other than the thread it was created on

当您试图从单独的线程更新一个win form时,您将得到如下错误信息: "Cross-thread operation not valid: Control 'progressBar1' accessed from a thread other than the thread it was created on." 本文将介绍如何处理此错误: 问题: 重现该错误, 添加一个 progress bar 控件 (progressbar1) 以及一个  button(btnStart)到您的

Android Framework中的线程Thread及它的threadLoop方法

当初跟踪Camera的代码中的时候一直追到了HAL层,而在Framework中的代码看见了若干个Thread.它们普遍的特点就是有一个threadLoop方法.按照字面的意思应该是这个线程能够循环处理数据.对应我想到到了java上层中的HandlerThread,这个估计也差不多,但当时心里总有一个疙瘩,想弄清楚它到底是怎么循环起来的. Android中java世界的Thread 先来看看java是怎么创建一个线程的.这个是最舒服的,也是我最熟悉的. new Thread(new Runnabl