一種WPF在后台線程更新UI界面的簡便方法


WPF框架規定只有UI線程(主線程)可以更新界面,所有其他后台線程無法直接更新界面。幸好,WPF提供的SynchronizationContext類以及C#的Lambda表達式提供了一種方便的解決方法。以下是代碼:

public static SynchronizationContext s_SC = Synchronization.Current; //主窗口類的靜態成員
 
在App類中:
static volatile int s_nMainThreadID = Thread.CurrentThread.ManagedThreadId; //這個變量保存主線程ID(UI線程),為下面的屬性服務, 注意volatile修飾符,如果不用的話,在Release版本的程序可能會出錯。
//這個屬性表示當前執行線程是否在主線程中運行
public static bool IsRunInMainThread { get { return Thread.CurrentThread.ManagedThreadId == s_nMainThreadID;}}
 
//這個函數用於設置UI界面上的某個元素
public void SetText(string strText)
{
  if (!App.IsRunInMainThread)
  {
    s_SC.Post(oo => { SetText(strText); }, null); //可以使用Post也可以使用Send
    return;
  }
  textBlock1.Text = strText;
}
 
//這個函數用於從UI界面的元素獲取內容
public string GetText()
{
  if (!App.IsRunInMainThread)
  {
    string str = null;
    s_SC.Send(oo => { str = GetText(); }, null);   //必須要使用Send
    return str;
  }
  return textBlock1.Text;
}
 
 
說明:雖然在主線程,也可以使用SynchronizationContext來更新界面,但那樣做會導致性能大幅下降。例如以下兩句語句的性能差距大約是 15倍(假設都在主線程調用)
textBlock1.Text = "Hello";                //執行100萬次用時1秒
s_SC.Send(oo => { textBlock1.Text = "Hello"; }, null);    //執行100萬次用時15秒
所以,每次執行界面更新函數時,判斷是否在主線程執行是必要的。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM