国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

窗體與子線程的交互

2019-11-14 16:32:08
字體:
來源:轉載
供稿:網友

窗體與子線程間通訊方法

窗體上的UI默認情況下不允許使用子線程(或者其它非創建控件的UI線程)去控制(這在NET2.0以下是允許的,但是考慮到安全性等問題,從2.0開始就禁止使用這個功能,除非Form的CheckForIllegalCrossThreadCalls=true,不推薦這樣使用)。

那么怎么辦呢?

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一定是開辟一個線程去執行的。


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 巫溪县| 黄冈市| 嘉黎县| 达拉特旗| 馆陶县| 定南县| 连平县| 江山市| 绥芬河市| 和田市| 嵩明县| 六盘水市| 陇川县| 天津市| 广州市| 旺苍县| 项城市| 哈巴河县| 萝北县| 新郑市| 罗平县| 周口市| 清水河县| 景德镇市| 淳化县| 揭西县| 威信县| 淮阳县| 额敏县| 泰和县| 新沂市| 绥德县| 贵阳市| 木兰县| 平舆县| 海安县| 丰台区| 平昌县| 游戏| 化州市| 温州市|