天天看點

WPF--->DispatcherObject

文章目錄

    • 初識
    • 走近
    • 接觸
      • 使用Dispatcher
        • 同步使用Dispatcher
        • 異步BeginInvoke
    • 參考

初識

所有 WPF 應用程式啟動時都會加載兩個重要的線程:

  • 一個用于呈現使用者界面,另一個用于管理使用者界面。
  • 呈現線程是一個在背景運作的隐藏線程,是以您通常面對的唯一線程 就是 UI 線程。
  • WPF 要求将其大多數對象與 UI 線程進行關聯。這稱之為線程關聯,意味着要使用一個 WPF 對象,隻能在建立它的線程上使用。在其他線程上使用它會導緻引發運作時異常。
  • UI 線程的作用是用于接收輸入、處理事件、繪制螢幕以及運作應用程式代碼。

     在 WPF 中絕大部分控件都繼承自 DispatcherObject,甚至包括 Application。這些繼承自 DispatcherObject 的對象具有線程關聯特征,也就意味着隻有建立這些對象執行個體,且包含了 Dispatcher 的線程(通常指預設 UI 線程)才能直接對其進行更新操作。

走近

DispatcherObject 類有兩個主要職責:

  • 提供對對象所關聯的目前 Dispatcher 的通路權限
  • 提供方法以檢查 (CheckAccess) 和驗證 (VerifyAccess) 某個線程是否有權通路對象(派生于 DispatcherObject)。CheckAccess 與 VerifyAccess 的差別在于 CheckAccess 傳回一個布爾值,表示目前線程是否有可以使用的對象,而 VerifyAccess 則線上程無權通路對象的情況下引發異常。

接觸

  • 在 WPF 中,DispatcherObject 隻能通過與它關聯的 Dispatcher 進行通路。 例如,背景線程不能更新由 UI 線程建立的 Label的内容。

    那麼如何更新UI線程建立的對象資訊呢?

    Dispatcher提供了兩個方法,Invoke和BeginInvoke,這兩個方法還有多個不同參數的重載。

    其中Invoke内部還是調用了BeginInvoke,一個典型的BeginInvoke參數如下:

  • Invoke 是同步操作,而 BeginInvoke 是異步操作。

    該這兩個操作将按指定的 DispatcherPriority 添加到 Dispatcher 的隊列中。

  • DispatcherPriority定義了很多優先級,可以分為前台優先級和背景優先級,其中前台包括 Loaded-Send,背景包括Background-Input。剩下的幾個優先級除了Invalid和Inactive都屬于空閑優先級。這個前台優先級和背景優先級的分界線是以Input來區分的,這裡的Input指的是鍵盤輸入和滑鼠移動、點選等等。

使用Dispatcher

同步使用Dispatcher

private void ModifyUI()

    {
        // 模拟一些工作正在進行
        Thread.Sleep(TimeSpan.FromSeconds(2));

        //xaml代碼未列出,lblHello出自 <Label x:Name="lblHello"/>
        this.Dispatcher.Invoke(DispatcherPriority.Normal, (ThreadStart)delegate()
        {
            lblHello.Content = "歡迎你光臨WPF的世界,Dispatche  同步方法 !!";
        });
}
           

異步BeginInvoke

private void btnAppBeginInvoke_Click(object sender, RoutedEventArgs e)
    {
               new Thread(() =>
        {
            Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Normal,
                new Action(() =>
                {
                    Thread.Sleep(TimeSpan.FromSeconds(2));
                    this.lblHello.Content = "歡迎你光臨WPF的世界,Dispatche 異步方法!!"+ DateTime.Now.ToString();
                }));
        }).Start();
    }
           

參考

WPF線程詳解之(一)——Dispatcher詳解

繼續閱讀