您的位置:首页 > 其它

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

2015-02-06 10:48 423 查看

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

分类:
.Net开发 2007-12-10 14:16
16819人阅读 评论(6)
收藏
举报

buttonexception测试ui.netobject

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.Stopwatch sw
=
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.Stopwatch sw
=
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, EventArgs e)





... {


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, EventArgs e)





... {



new System.Threading.Thread(
new System.Threading.ThreadStart(invokeThread)).Start();



new System.Threading.Thread(
new System.Threading.ThreadStart(invokeThread)).Start();


}


}


}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: