日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > asp.net >内容正文

asp.net

在.Net中进行跨线程的控件操作(上篇:Control.Invoke)

發(fā)布時間:2025/3/21 asp.net 20 豆豆
生活随笔 收集整理的這篇文章主要介紹了 在.Net中进行跨线程的控件操作(上篇:Control.Invoke) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

本文的重點在于介紹如何在多線程編程中,從非UI線程上訪問界面中的控件。有過多線程編程經(jīng)驗的人都知道,當(dāng)我們在非UI線程上試圖給一個界面中的控件賦值的時候,比如說label的Text屬性,系統(tǒng)會拋出一個下面的異常:

這是由于.Net中的大部分控件的實例都是非線程安全的,如果進行跨線程的訪問,可能會造成臟數(shù)據(jù),所以.Net默認(rèn)禁止這種跨線程的賦值操作。那要如何解決這個問題呢?

既然.Net禁止跨線程的賦值操作,那么需要給控件賦值的非UI線程就只有將這種賦值的請求傳遞給UI線程,最終由UI線程完成賦值的操作。如何傳遞這種請求?幸運的是,Control類提供了一個Invoke方法。這個方法的功能是將Invoke所指定的方法提交到生成這個Control的UI線程上執(zhí)行,也就是說我們可以通過調(diào)用這個Invoke方法,讓UI線程來執(zhí)行Invoke所指定的方法。 由于Invoke方法是一個public方法,所以所有繼承了Control類的.Net控件都可以調(diào)用這個方法。

我們來看一下Invoke方法的聲明:

1: public object Invoke(Delegate method);

對于這個Invoke方法,它的參數(shù)是一個委托類型,調(diào)用的時候指向那個你想讓UI線程執(zhí)行的方法,它的返回值是這個委托指定的方法的返回值。那么如果我想讓UI線程執(zhí)行一個帶參數(shù)的方法怎么辦呢?別著急,Invoke還有另外一個重載方法:

1: public object Invoke(Delegate method, params object[] args);

這個Invoke方法的參數(shù)除了委托類型外,還有一個不定長的參數(shù)數(shù)組,用來傳遞委托類型所指定的方法的參數(shù)。

有了這兩個Invoke方法后,我們在非UI線程中,如果需要給界面中的控件進行賦值操作的話,就可以調(diào)用控件的Invoke方法,讓Invoke方法去執(zhí)行給控件進行賦值的操作,這樣一來,實際執(zhí)行給控件賦值的操作就由UI線程執(zhí)行了。具體過程請參考下面的例子。

1: private void button1_Click(object sender, EventArgs e) 2: { 3: label1.Text = "開始了"; 4: Thread newThread = new Thread(new ThreadStart(DoWork)); 5: newThread.Start(); 6: } 7:? 8: public delegate void SampleDelegate(int i); 9:? 10: private void DoWork() 11: { 12: for (int i = 0; i < 10; i++) 13: { 14: System.Threading.Thread.Sleep(1000); 15: if (isCancel) 16: { 17: isCancel = false; 18: return; 19: } 20: SampleDelegate dele = new SampleDelegate(UpdateLabel); 21: label1.Invoke(dele, i); 22: } 23: } 24:? 25: private void UpdateLabel(int i) 26: { 27: label1.Text = "當(dāng)前i的值是:" + i.ToString(); 28: }

?

?

在上面的例子中,我啟動了一個新的線程來執(zhí)行DoWork,然后我在Label1中不停的刷新DoWork方法中的 i 的值,由于DoWork是在非UI線程執(zhí)行的,這樣我不能直接在DoWork中給Label1.Text賦值,所以,我把賦值操作定義到一個方法UpdateLabel中;然后定義一個委托類型(由于Invoke方法的第一個參數(shù)是一個委托類型)并實例化它,讓這個委托的實例指向UpdateLabel方法;最后我在DoWork中調(diào)用label1.Invoke方法,把執(zhí)行UpdateLabel的委托提交到UI線程進行執(zhí)行。這樣就完成了整個賦值的操作。

總之,Control.Invoke方法實際上并不是委托的執(zhí)行者,它僅僅是將委托傳遞給UI線程,而UI線程才是最終的委托的執(zhí)行者。所以大家不要被Invoke這個名稱所誤導(dǎo),實際上它根本沒有執(zhí)行Invoke操作,僅僅是做了Transfer操作。

最后,請大家仔細想一想,Invoke操作有沒有什么風(fēng)險?(提示:Control可是還提供了BeginInvoke方法哦~~)

來源:http://www.cnblogs.com/happinessCodes/archive/2010/07/19/1780964.html

轉(zhuǎn)載于:https://www.cnblogs.com/gjhjoy/p/3580526.html

總結(jié)

以上是生活随笔為你收集整理的在.Net中进行跨线程的控件操作(上篇:Control.Invoke)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。