`
xiaoer_1982
  • 浏览: 1815660 次
  • 性别: Icon_minigender_2
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

Control.CheckForIllegalCrossThreadCalls=false不可在多线中随便使用

阅读更多

CodeProject上有篇文章An Alternate Way of Writing a Multithreaded GUI in C#

本意是Alternate Way 另外一种方法,后来莫名其妙的被转载成中文变了题目,最高效的方法。

CheckForIllegalCrossThreadCalls和control.Invoke有什么不同,哪个更好用,更高效呢?
占在任何角度讲,都不要使用CheckForIllegalCrossThreadCalls,即便他运行和代码编写的确实比Invoke效率高
感兴趣的,可以参考我后面贴出的代码来测试对比一下两者的不同。这里我只简单说一下结论:
1、性能CheckForIllegalCrossThreadCalls=false时比invoke高,而且代码比较优雅。
测试时间如下:
Button1 ---------------------------
00:00:01.0760900
00:00:01.0771200
Button2 --------------------------
00:00:01.0812499
00:00:01.0813443
效率差多少?在这里时间还不到1%,代码少写一个if字句
看到有文章说这种方法在大量更新ui时会引发大量异常,导致性能下降
我测试了一下,耗时和循环次数是很平稳的线性关系,而且也没有发现几个Exception相关性能计数器有问题,这说明这又是某老外朋友想当然的说法。

2、CheckForIllegalCrossThreadCalls在.net1.x中默认是false,也就是不检查,.net2.0和3.x默认是true
说明这是ms有意的引导,说不定以后不让你改了。这也是很多1.x用户在刚用2.0时不习惯跨线程更新ui的原因之一。

3、死穴:安全性
CheckForIllegalCrossThreadCalls容许子线呈随时更新ui,在同一个test函数体内,不能保证自身事务的一致性。给label1付了值
一回头,就已经被别人改了,这和超市的踩踏事件的后果一样严重。
当然你可以自己加锁,用信号量,这样还不如直接使用Invoke了,你只是又把别人做好的事情做了一遍。

如果你觉的你的应用不会考虑在写入ui的同时来读取ui,而倾向使用CheckForIllegalCrossThreadCalls来追求效率的话,也是不恰当的做法。
首先CheckForIllegalCrossThreadCalls并不能让效率发生本质的变化。
其次需求永远是变化的,现在不考虑不等于以后不会碰到
听从ms的引导。否则以后要在高版本的.net framework中移植代码的时候需要花费数倍的人工。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace WindowsApplication34
... {
public partial class Form1:Form
... {
public Form1()
... {
InitializeComponent();
}




// 模拟一个实际应用
// 对label1付值后立马检查他的值,如果已经被改过则抛出异常

void test()
... {
string strText = Guid.NewGuid().ToString();
this .label1.Text = strText;
if ( this .label1.Text != strText)
... {
// 测试性能时把这一句注释掉!!!!!!!!!!!!!!!!!!!!!!1
throw new Exception( " label1的值意外改变 " );
}

}


// 不使用invoke方法直接进入Control
void doThread()
... {
System.Diagnostics.Stopwatchsw
= new System.Diagnostics.Stopwatch();
sw.Reset();
sw.Start();
for ( int i = 0 ;i < 100 ;i ++ )
... {
test();
System.Threading.Thread.Sleep(
10 );
}

sw.Stop();
Console.WriteLine(sw.Elapsed);
}


// 使用invoke方法
public delegate void dTest();
void invokeThread()
... {
System.Diagnostics.Stopwatchsw
= new System.Diagnostics.Stopwatch();
sw.Reset();
sw.Start();
for ( int i = 0 ;i < 100 ;i ++ )
... {
if ( this .InvokeRequired)
... {
this .Invoke( new dTest(test));
}

else
... {
test();
}

System.Threading.Thread.Sleep(
10 );
}

sw.Stop();
Console.WriteLine(sw.Elapsed);
}



// 通过CheckForIllegalCrossThreadCalls的值忽略跨线程错误,这时会抛出异常
private void button1_Click( object sender,EventArgse)
... {
Form1.CheckForIllegalCrossThreadCalls
= false ;
new System.Threading.Thread( new System.Threading.ThreadStart(doThread)).Start();
new System.Threading.Thread( new System.Threading.ThreadStart(doThread)).Start();

}

// 通过invoke方法,在主线程排队,lable1的值在test函数体内永远是线程安全的.
private void button2_Click( object sender,EventArgse)
... {
new System.Threading.Thread( new System.Threading.ThreadStart(invokeThread)).Start();
new System.Threading.Thread( new System.Threading.ThreadStart(invokeThread)).Start();
}

}

}
分享到:
评论

相关推荐

    C#串口间通讯

    C#串口间通讯using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing;... Control.CheckForIllegalCrossThreadCalls = false; }

    TCP/UDP网络调试助手

    Control.CheckForIllegalCrossThreadCalls = false; } string GetAddressIP() { string AddressIP = ""; foreach (IPAddress _IPAddress in Dns.GetHostEntry(Dns.GetHostName()).AddressList) { if (_IP...

    c# socket 编程

    c# socket编程源代码 private IPEndPoint ServerInfo; private Socket ClientSocket;... CheckForIllegalCrossThreadCalls = false; this.UserName.Text = Environment.MachineName; } ...............

    CameraPlayingVideo.7z

    c#调用摄像头进行录像、拍照、播放视频、保存录像,可调整分辨率和帧数对视频清晰度进行调节,很实用。当需要对视频进行分割保存... PictureBox.CheckForIllegalCrossThreadCalls = false; LogThread.Start();//起线程

    C# Socket聊天室例子

    Control.CheckForIllegalCrossThreadCalls = false; } private void btnConnect_Click(object sender, EventArgs e) { switch (_frmLogin.ShowDialog()) { case DialogResult.OK://使用的是一个已经存在的...

    串口调试助手

    实现串口通信 十六进制 通信 using System;... Control.CheckForIllegalCrossThreadCalls = false;//允许跨线程访问控件 } //发送按钮 private void button1_Click(object sender, EventArgs e) {

    CPU、内存使用率

    Control.CheckForIllegalCrossThreadCalls = false; MyProcesses = Process.GetProcesses(); tsslNum.Text = "进程数: " + MyProcesses.Length.ToString() + " | CPU使用:"; td = new Thread(new ThreadStart...

    C#客户端通信

    Control.CheckForIllegalCrossThreadCalls = false; } private void btnconnect_Click(object sender, EventArgs e)//客户端请求连接 { try { int portnumber = Convert.ToInt32(txtport.Text);//port...

    vb.net2012操作跨窗体控件(单线程和多线程两种方法)实例

    在码农的生活中,很多级码农都有这样的经历,会被一个小小的技术问题拦住,然后进度跟不上了,被老板XXXX一大通了。心情不爽了。 好吧,这个曾经是我遇到拦路虎之一。但事实上不是什么大技术。技术就是一层纸,破了...

    C#中跨线程访问控件问题解决方案分享

    第二种方法是禁止编译器对跨线程访问作检查,可以实现访问,但是出不出错不敢保证Control.CheckForIllegalCrossThreadCalls = false; 最近我在做一个项目,遇到了跨线程要去访问页面控件.但是总是提示出错,不能在其它...

    Socket简单通讯

    CheckForIllegalCrossThreadCalls = false;//不捕获对错误线程的调用 this.CmdStar.Enabled = false; this.CmdStop.Enabled = true; this.StateMsg.Text = "服务正在运行..." + " 运行端口:" + this.GetPort()....

    C#制作简单正则表达式测试器

    CheckForIllegalCrossThreadCalls = false; } private void btnPi_Click(object sender, EventArgs e) { if (regText.Text.Trim() != "") { ParameterizedThreadStart ts = new ParameterizedThreadStart(P)...

    c#聊天客户端

    CheckForIllegalCrossThreadCalls = false; this.loginUsers_label.Text = Environment.MachineName; //服务端IP和端口信息设定,这里的IP可以是127.0.0.1,可以是本机局域网IP,也可以是本机网络IP ServerInfo ...

    C#的回调机制浅析

    将检查合法跨线程调用设置为 false 表示不检查 项目开发中不允许这样使用,因此会导致非线程安全而出现奇葩BUG。 4.初始化回调方法(本质为实例化委托)。 5.必须先启动线程,再进行阻塞操作,否则将等待阻塞操作...

    C#?副线程调用主线程的控件

     System.Windows.Forms.Control.CheckForIllegalCrossThreadCalls = false;  2、副线程函数中通过Control.Invoke(Delegate d)来通过委托方式来调用处理控件的方法。  线程函数: private void go() { ...

    Invoke跨线程调用的代码

    忽略跨线程访问的错误 CheckForIllegalCrossThreadCalls = false,但是这个方法很不稳定,使用invoke方法解决跨线程访问的问题,里边有2个例子, 通过自己额外创建的线程改变label控件中的内容从而验证invoke方法

    c#异步读取数据库与异步更新ui的代码实现

    a2.CheckForIllegalCrossThreadCalls = false; //a2为窗体名称 下面的代码就是从数据库里取得数据并绑定 代码如下:private void button1_Click(object sender, EventArgs e) { SqlConnection con; SqlCommand ...

    C#定时调用方法(线程)

    Form.CheckForIllegalCrossThreadCalls = false; //禁止软件对于不符合原则的跨线程运行的程序进行检查 InitializeComponent(); } Thread t; //定义一个线程 private void Form1_Load(object sender

    c# 加密和解密相关代码

    序中判断是否为数字的方法有很多种,可以使用正则表达式、int.Parse 方法和double.Parse 方法等。下面的代码 通过double.Parse 方法判断textBox1 文本框中的输入是否为数字。 double.Parse(textBox1.Text); 实例573 ...

    WinForm窗体调用WCF服务窗体卡死问题

    窗体启动会启动一个程序主线程,如果在From_Load()方法中调用服务,调用服务操作会阻塞主程序。 只需要将调用服务的操作放到其他线程中处理就可以解决这个问题。 比如: 代码如下: Thread ServiceThread=null; ...

Global site tag (gtag.js) - Google Analytics