Wednesday, March 23, 2016

Update UI from Background Thread

有玩過 Threading 既都可能知道, background thread 係唔可以直接 update UI 既野.
今次學玩 C#, 當然又要研究下.  So far 都好多方法..

1) 用 Application.Current.Dispatcher.BeginInvoke, 簡單直接了當:

     Application.Current.Dispatcher.BeginInvoke(
        System.Windows.Threading.DispatcherPriority.Normal,
        (Action)(() => txtRequest.Text = requestText));


有時候, 可能同一個 function, 有機會被 UI Thread call, 亦可能被 background thread call, 為避把 UI update 的地方都重複, 可以做一個負責 update UI 既 function, 從中檢查是否在 UI Thread, 如果是的話就直接更新, 否則就用上面的方法, 去 call 自己一次, 就會回到 UI thread 了.

檢查 是否在 UI Thread, 可以用 Dispatcher.FromThread(Thread.CurrentThread), 如果回傳 null, 就即是不在 UI Thread 了.

以下是一個簡單例子:
     
using System.Windows.Threading;
:
:
public void UpdateUI(string data) {
  if (System.Windows.Threading.Dispatcher.FromThread(Thread.CurrentThread) == null) {
      Application.Current.Dispatcher.BeginInvoke(
        System.Windows.Threading.DispatcherPriority.Normal,
        (Action)(() => UpdateUI(data)));
      return;
  } 
  // It's now in UI Thread, it can update UI directly
  :
  :
}

2) 如果只係針對某個 field 既 update, 未必需要用 Application.CurrentDispatcher, 可以用 <Control>.Dispatcher.
     this.txtRequest.Dispatcher.Invoke(
        System.Windows.Threading.DispatcherPriority.Normal,
        (Action)(() => txtRequest.Text = requestText));


補充少少, Invoke 同 BeginInvoke 既分別:
  • Invoke - synchronous call, 要行完先至會繼續落去
  • BeginInvoke - asynchronous call, 唔駛等行完就繼續落去了.

如果無需要等既, 就無謂等了, 用 BeginInvoke 可以去得快 D.

但係, 如果你要 retrieve UI 既野, 又或者D 野有先後次序, 比如想 read txtRequest.Text 既話, 當然係要等佢番左黎先行得, 就要用 Invoke 了.

No comments:

Post a Comment