C#完成窗體與子線程的交互的辦法。本站提示廣大學習愛好者:(C#完成窗體與子線程的交互的辦法)文章只能為提供參考,不一定能成為您想要的結果。以下是C#完成窗體與子線程的交互的辦法正文
本文實例簡述了C#完成窗體與子線程間通信的辦法,關於C#初學者有必定的自創價值。詳細辦法以下:
普通來講窗體上的UI在默許情形下不許可應用子線程(或許其它非創立控件的UI線程)去掌握(這在NET2.0以下是許可的,然則斟酌到平安性等成績,從2.0開端就制止應用這個功效,除非Form的CheckForIllegalCrossThreadCalls=true,不推舉如許應用)。
那末若何完成C#窗體與子線程的交互呢?詳細辦法以下:
1、應用Invoke或許BeginInvoke辦法:
用一個線程,裡邊挪用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:這裡的“異步”其實不是針對UI線程,而是說當Control的BeginInvoke在某個子線程中挪用時,子線程中BeginInvoke前面的代碼(彈出“Finished”框框)會先履行,然後比及BeginInvoke中的誰人拜托辦法完整履行終了以後Label才會被賦值。假如改成Invoke,那末“OK”永久在Invoke的拜托代碼完全履行終了以後才被履行。
所以BeginInvoke=Invoke(在UI主線程中,所以不建議在主線程中直接如許挪用)
2、線程同步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相似,須要留意:
1)SynchronizationContext:惟獨在UI窗體線程中會主動初始化(button1_Click事宜中SynchronizationContext.Current為以後窗體),其它線程與線程要交互,必需經由過程new SynchronizationContext()完成)。
2)Post辦法同等於BeginInvoke感化,Send同等於Invoke感化。
年夜家假如細心試驗代碼,還會發明不管何種情形,彈出“Finished”框框老是界面“假逝世”3秒,是的,證實了以上4個辦法都是在UI線程上履行的(只不外是同步或許異步向窗體新聞泵發送信息罷了)。所以應當“一次性地把數據在子線程中先全體處置清潔(在Invoke,BeginInvoke,Send或許Post前得出成果,寫代碼),然後一次性發送告訴給窗體,更新界面便可)。
另外還須要留意:
任何拜托(Delegate)也有BeginInvoke辦法,它是真實的異步,一旦Invoke必定是開拓一個線程去履行的。