1. 程式人生 > >[轉]C#子執行緒更新UI控制元件的方法例項總結

[轉]C#子執行緒更新UI控制元件的方法例項總結

[我的評論:之前專案做的C#客戶端對於多執行緒修改UI使用的就是這個,找了好些時間才找到,其他很多都是沒有再函式中直接使用Action<>放置delegate的,而是在全域性下先放一個delegate的宣告,很頭疼,特轉]

[來源:http://www.jb51.net/article/55186.htm (來源也標名轉載,可能不是最初來源)]

這篇文章主要介紹了C#子執行緒更新UI控制元件的方法,在桌面應用程式中控制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屬性

private void button6_Click(object sender, EventArgs e) 
{ 
   Thread demoThread =new Thread(new ThreadStart(threadMethod)); 
   demoThread.IsBackground = true; 
   demoThread.Start();//啟動執行緒 
} 
  
 void threadMethod() 
 {  
   Action<String> AsyncUIDelegate=delegate(string n){label1.Text=n;};/<span style="font-family: Arial, Helvetica, sans-serif;">/定義一個委託</span> 
   label1.Invoke(AsyncUIDelegate,new object[]{"修改後的label1文字"}); 
 } 

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

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

public virtual void Post(SendOrPostCallback d,Object state)    //將非同步訊息排程到一個同步上下文

可以看出我們要非同步更新UI控制元件,第一是要獲取UI執行緒的上下文了,第二就是呼叫post方法了,程式碼實現:

SynchronizationContext _syncContext = null; 
  
private void button6_Click(object sender, EventArgs e) 
{ 
  Thread demoThread =new Thread(new ThreadStart(threadMethod)); 
  demoThread.IsBackground = true; 
  demoThread.Start();//啟動執行緒 
} 
  
//窗體建構函式   
public Form1() 
{ 
  InitializeComponent(); 
   //獲取UI執行緒同步上下文 
  _syncContext = SynchronizationContext.Current; 
} 
  
private void threadMethod() 
{ 
   _syncContext.Post(SetLabelText, "修改後的文字");//子執行緒中通過UI執行緒上下文更新UI 
} 
   
private void SetLabelText(object text) 
{ 
  this.lable1.Text = text.ToString(); 
}

希望本文所述對大家的C#程式設計有所幫助