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
  • 相关阅读:
    Python 元胞自动机模拟——生命游戏
    ()python画动态图——plt.ion动图使用,训练过程展示
    Python——因子分析(KMO检验和Bartlett's球形检验)
    bind(),unbind(),hover(),toggle(),animate()
    多计算机通信中的时间同步问题
    如何创建自定义尺寸的空白地图
    ROS中的珊格地图——nav_msgs::OccupancyGrid
    c++使用eigen库,矩阵维度错误
    Eigen 求最小二乘
    Mybatis 框架下 SQL 注入攻击的 3 种方式,真是防不胜防!
  • 原文地址:https://www.cnblogs.com/DoNetCoder/p/4369903.html
Copyright © 2011-2022 走看看