[C#.NET(WinForm)] – Control.CheckForIllegalCrossThreadCalls=false不可在多線中隨便使用

來源:互聯網
上載者:User

來源:http://blog.csdn.net/jinjazz/archive/2007/12/10/1927126.aspx

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.Linq;
using System.Text;
using System.Windows.Forms;

namespace WindowsFormsApplication1
{
publicpartialclass Form1 : Form
{
public Form1()
{
InitializeComponent();
}

// 類比一個實際應用
// 對label1付值後立馬檢查他的值,如果已經被改過則拋出異常

void test()
{
string strText = Guid.NewGuid().ToString();
this.label1.Text = strText;
}

// 不使用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方法
publicdelegatevoid 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的值忽略跨線程錯誤,這時會拋出異常
privatevoid 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函數體內永遠是安全執行緒的.
privatevoid 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();
}
}
}

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.