zoukankan      html  css  js  c++  java
  • WPF:浅析Dispatcher

    本人文笔差。还是直接上代码吧。(本文假设你对WPF中的Dispatcher有一定的了解)

    你觉得下面的代码可以正常执行吗?

            private void Button_Click(object sender, RoutedEventArgs e)
            {
                Thread t = new Thread(() =>
                {
                    while (true)
                    {
                        new Window().Show();
                        Thread.Sleep(1000);
                    }
                });
                t.Start();
            }

    WPF的操作UI的线程必须是单线程单元模型(STA),也就是必须把线程的单元状态设置为STA才可以操作UI对象。

    上面的代码,并没有设置线程的单元状态,线程的默认单元状态为:System.Threading.ApartmentState.Unknown

    通过下面的代码可以设置线程的单元状态为STA:

    t.TrySetApartmentState(ApartmentState.STA);

    修改后的代码如下:(可以正常运行)

            private void Button_Click(object sender, RoutedEventArgs e)
            {
                Thread t = new Thread(() =>
                {
                    while (true)
                    {
                        new Window().Show();
                        Thread.Sleep(1000);
                    }
                });
                t.TrySetApartmentState(ApartmentState.STA);
                t.Start();
            }

    接下来,对代码再做一点修改,你觉得下面的代码是否可以正常运行呢?

            private void Button_Click(object sender, RoutedEventArgs e)
            {
                Thread t = new Thread(() =>
                {
                    while (true)
                    {
                        Window win = new Window();
    
                        this.Dispatcher.Invoke(new Action(delegate
                            {
                                win.Show();
                            }));
                        Thread.Sleep(1000);
                    }
                });
    
                t.TrySetApartmentState(ApartmentState.STA);
                t.Start();
            }

     在一个线程中创建的UI对象,也只能是创建该UI对象的线程才能访问它。如果其他线程要访问这个UI对象,需要通过创建UI线程的Dispatcher才能实现。

    上面的代码,win对象实际上是t这个线程创建的。而执行win.Show()这个动作的却是另外这个线程(实际上是主UI线程),所以上面的代码也是不能正常执行的。

    需要注意的是,只有当一个线程中执行过UI操作后,这个线程才具有Dispatcher,然后其他线程可以通过这个Dispatcher去访问该线程创建的UI对象。一个没有执行任何UI操作的线程,其Dispatcher为null.

    通过Dispatcher的静态方法FromThread可以获取一个线程关联的Dispatcher对象。如果你觉得上面的这句话不好理解,可以看看下面的图:

    看以看到,在没有执行UI操作之前,线程t的Dispatcher对象的值为null,当执行完Window win = new Window();后(也就是执行了一个UI操作),t线程关联的Dispatcher就有值了。

    总结:

    1. 任何线程中如果想执行UI操作,那么其线程单元必须设置为STA。
    2. 一个线程如果创建了UI对象,那么这个UI对象就只能被这个线程管理。
    3. 任何线程如果需要访问其他的线程创建的UI对象,只能通过其他线程的Dispatcher进行访问
    4. 一个线程如果没有执行任何UI操作,那么其关联的Dispatcher为null
  • 相关阅读:
    eclipse中文乱码问题解决方案
    修改Tomcat的JDK目录
    Tomcat 5.5 修改服务器的侦听端口
    HTML DOM教程 27HTML DOM Button 对象
    HTML DOM教程 24HTML DOM Frameset 对象
    Navicat for MySQL v8.0.27 的注册码
    HTML DOM教程 25HTML DOM IFrame 对象
    Tomcat 5.5 的下载和安装
    android manifest相关属性
    ubuntu10.04 下 eclipse 小结
  • 原文地址:https://www.cnblogs.com/DoNetCoder/p/4369903.html
Copyright © 2011-2022 走看看