C#子線程更新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;};//定義一個委託
        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();
}



發佈了34 篇原創文章 · 獲贊 6 · 訪問量 9萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章