C#實(shí)現(xiàn)窗體與子線(xiàn)程的交互的方法
本文實(shí)例簡(jiǎn)述了C#實(shí)現(xiàn)窗體與子線(xiàn)程間通訊的方法,對(duì)于C#初學(xué)者有一定的借鑒價(jià)值。具體方法如下:
一般來(lái)說(shuō)窗體上的UI在默認(rèn)情況下不允許使用子線(xiàn)程(或者其它非創(chuàng)建控件的UI線(xiàn)程)去控制(這在NET2.0以下是允許的,但是考慮到安全性等問(wèn)題,從2.0開(kāi)始就禁止使用這個(gè)功能,除非Form的CheckForIllegalCrossThreadCalls=true,不推薦這樣使用)。
那么如何實(shí)現(xiàn)C#窗體與子線(xiàn)程的交互呢?具體方法如下:
一、使用Invoke或者BeginInvoke方法:
用一個(gè)線(xiàn)程,里邊調(diào)用Invoke或者BeginInvoke方法即可:
public partial class Form1 : Form
{
public void Processing(int num)
{
int answer = 2;
Task t = new Task(() =>
{
for (int i = 3; i <= num; i++)
{
answer *= i;
}
this.BeginInvoke(new MethodInvoker(() => { Thread.Sleep(3000); MessageBox.Show("Finished!") }));
MessageBox.Show("OK");
});
t.Start();
}
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
MessageBox.Show("First!");
Processing(10);
}
}
這里值得注意:
1)BeginInvoke:這里的“異步”并不是針對(duì)UI線(xiàn)程,而是說(shuō)當(dāng)Control的BeginInvoke在某個(gè)子線(xiàn)程中調(diào)用時(shí),子線(xiàn)程中BeginInvoke后面的代碼(彈出“Finished”框框)會(huì)先執(zhí)行,然后等到BeginInvoke中的那個(gè)委托方法完全執(zhí)行完畢之后Label才會(huì)被賦值。如果改成Invoke,那么“OK”永遠(yuǎn)在Invoke的委托代碼徹底執(zhí)行完畢之后才被執(zhí)行。
所以BeginInvoke=Invoke(在UI主線(xiàn)程中,所以不建議在主線(xiàn)程中直接這樣調(diào)用)
二、線(xiàn)程同步SynchronizedContext:
public partial class Form1 : Form
{
public void Processing(int num,SynchronizationContext context)
{
int answer = 2;
Task t = new Task(() =>
{
for (int i = 3; i <= num; i++)
{
answer *= i;
}
SynchronizationContext.SetSynchronizationContext(context);
SynchronizationContext.Current.Post((obj) => { Thread.Sleep(3000); MessageBox.Show("Finished"); }, null);
MessageBox.Show("Last");
});
t.Start();
}
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
MessageBox.Show("First!");
Processing(10,SynchronizationContext.Current);
}
}
和BeginInvoke、Invoke類(lèi)似,需要注意:
1)SynchronizationContext:唯獨(dú)在UI窗體線(xiàn)程中會(huì)自動(dòng)初始化(button1_Click事件中SynchronizationContext.Current為當(dāng)前窗體),其它線(xiàn)程與線(xiàn)程要交互,必須通過(guò)new SynchronizationContext()實(shí)現(xiàn))。
2)Post方法等同于BeginInvoke作用,Send等同于Invoke作用。
大家如果仔細(xì)實(shí)驗(yàn)代碼,還會(huì)發(fā)現(xiàn)無(wú)論何種情況,彈出“Finished”框框總是界面“假死”3秒,是的,證明了以上4個(gè)方法都是在UI線(xiàn)程上執(zhí)行的(只不過(guò)是同步或者異步向窗體消息泵發(fā)送信息而已)。所以應(yīng)該“一次性地把數(shù)據(jù)在子線(xiàn)程中先全部處理干凈(在Invoke,BeginInvoke,Send或者Post前得出結(jié)果,寫(xiě)代碼),然后一次性發(fā)送通知給窗體,更新界面即可)。
此外還需要注意:
任何委托(Delegate)也有BeginInvoke方法,它是真正的異步,一旦Invoke一定是開(kāi)辟一個(gè)線(xiàn)程去執(zhí)行的。
- C#線(xiàn)程同步的三類(lèi)情景分析
- C#簡(jiǎn)單多線(xiàn)程同步和優(yōu)先權(quán)用法實(shí)例
- c#線(xiàn)程同步使用詳解示例
- c#.net多線(xiàn)程編程教學(xué)——線(xiàn)程同步
- C#之WinForm跨線(xiàn)程訪(fǎng)問(wèn)控件實(shí)例
- C#實(shí)現(xiàn)終止正在執(zhí)行的線(xiàn)程
- C#傳遞參數(shù)到線(xiàn)程的方法匯總
- C#實(shí)現(xiàn)線(xiàn)程池的簡(jiǎn)單示例
- c#多線(xiàn)程編程基礎(chǔ)
- C#中線(xiàn)程同步對(duì)象的方法分析
相關(guān)文章
C#實(shí)現(xiàn)動(dòng)態(tài)生成靜態(tài)頁(yè)面的類(lèi)詳解
這篇文章主要介紹了C#實(shí)現(xiàn)動(dòng)態(tài)生成靜態(tài)頁(yè)面的類(lèi),結(jié)合實(shí)例形式詳細(xì)分析了C#動(dòng)態(tài)生成靜態(tài)頁(yè)面的原理與相關(guān)使用技巧,需要的朋友可以參考下2016-04-04
c#循環(huán)中產(chǎn)生偽隨機(jī)數(shù)
在循環(huán)中產(chǎn)生多個(gè)隨機(jī)數(shù),容易出現(xiàn)連續(xù)相同的數(shù)據(jù),最終的多個(gè)隨機(jī)數(shù)并不隨機(jī),而是帶有某種規(guī)律性。2010-06-06
C#自定義實(shí)現(xiàn)多程序共享內(nèi)存空間
這篇文章主要為大家詳細(xì)介紹了C#如何自定義實(shí)現(xiàn)多程序共享內(nèi)存空間,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2024-10-10
C#用ComboBox控件實(shí)現(xiàn)省與市的聯(lián)動(dòng)效果的方法
這篇文章主要介紹了C#用ComboBox控件實(shí)現(xiàn)省與市的聯(lián)動(dòng)效果的方法,較為詳細(xì)的分析了ComboBox控件的使用原理與相關(guān)技巧,需要的朋友可以參考下2015-01-01
C#中DateTimePicker默認(rèn)值顯示為空的問(wèn)題
這篇文章主要介紹了C#中DateTimePicker默認(rèn)值顯示為空的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-06-06

