天天看點

C#子線程中更新ui

本文執行個體總結了C#子線程更新UI控件的方法,對于桌面應用程式設計的UI界面控制來說非常有實用價值。分享給大家供大家參考之用。具體分析如下:

一般在winform C/S程式中經常會在子線程中更新控件的情況,桌面程式UI線程是主線程,當試圖從子線程直接修改控件屬性時會出現“從不是建立控件的線程通路它”的異常提示。

跨線程更新UI控件的常用方法有兩種:

1.使用控件自身的invoke/BeginInvoke方法

2.使用SynchronizationContext的Post/Send方法更新

具體實作如下:

1.使用控件自身的invoke/BeginInvoke方法

Control類實作了ISynchronizeInvoke 接口。

Control類的invoke方法有兩個實作

Object Invoke(Delegate); //在擁有此控件的基礎視窗句柄的線程上執行指定的委托
Object Invoke(Delegate,Object[] );      

可以看出繼承Control類的UI控件都可以使用Invoke方法異步更新。以下代碼段實作在子線程中更新Label控件的Text屬性

1. private void button6_Click(object sender, EventArgs e)
2. {
3. new Thread(new ThreadStart(threadMethod));
4. true;
5. //啟動線程
6. }
7. 
8. void threadMethod()
9. {
10. delegate(string n){label1.Text=n;};/<span style="font-family: Arial, Helvetica, sans-serif;">/定義一個委托</span>
11. new object[]{"修改後的label1文本"});
12. }      

2.使用SynchronizationContext的Post/Send方法更新

SynchronizationContext類在System.Threading指令空間下,可提供不帶同步的自由線程上下文,其中Post方法簽名如下:

public virtual void Post(SendOrPostCallback d,Object state)    //将異步消息排程到一個同步上下文

可以看出我們要異步更新UI控件,第一是要擷取UI線程的上下文了,第二就是調用post方法了,代碼實作:

1. SynchronizationContext _syncContext = null;
2. private void button6_Click(object sender, EventArgs e)
3. {
4. new Thread(new ThreadStart(threadMethod));
5. true;
6. //啟動線程
7. }
8. //窗體構造函數
9. public Form1()
10. {
11. InitializeComponent();
12. //擷取UI線程同步上下文
13. _syncContext = SynchronizationContext.Current;
14. }
15. private void threadMethod()
16. {
17. "修改後的文本");//子線程中通過UI線程上下文更新UI
18. }
19. private void SetLabelText(object text)
20. {
21. this.lable1.Text = text.ToString();
22. }