天天看点

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详解

继续阅读