• 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
  • 相关阅读:
    jmeter HTTP请求之content-type
    MyEclipse10中导入的jquery文件报错(出现红叉叉,提示语法错误)
    MyEclipse使用总结——使用MyEclipse打包带源码的jar包
    MyEclipse使用总结——MyEclipse10安装SVN插件
    Java调用K3Cloud的密码加密算法实现登录密码检验
    Sencha Touch 2 实现跨域访问
    K/3Cloud二次开发基于WebDev附加进程调试
    如何把子单据体的数值合计到单据体上
    移动开发规范概述
    使用HttpWebRequest post数据时要注意UrlEncode
  • 原文地址:https://www.cnblogs.com/DoNetCoder/p/4369903.html
Copyright © 2020-2023  润新知