zoukankan      html  css  js  c++  java
  • WPF多线程更新UI的一个解决途径

    那么该如何解决这一问题呢?通常的做法是把耗时的函数放在线程池执行,然后切回主线程更新UI显示。前面的updateTime函数改写如下:

        private async void updateTime()
        {
            while (true)
            {
                await Task.Run(() => Thread.Sleep(900));
                textBlock.Text = DateTime.Now.ToString();
                await Task.Delay(100);
            }
        }

    这种方式能满足我们的大部分需求。但是,有的操作是比较耗时间的。例如,在多窗口实时监控的时候,我们就需要同时多十来个屏幕每秒钟各进行几十次的刷新,更新图像这个操作必须在UI线程上进行,并且它有非常耗时间,此时又会回到最开始的卡顿的情况。

    看起来这个问题无法解决,实际上,WPF只是不允许跨线程访问程序,并非不允许多线程更新界面。我们大可以对每个视频监控窗口单独其一个独立的线程,在那个线程中进行更新操作,此时就不会影响到主线程。MSDN上有篇文章介绍了详细的操作:Multithreaded UI: HostVisual。用这种方式将原来的程序改写如下:

     e)
        {
            ();

            (hostVisual);
            .Content = content;

            (() =>
            {
                (hostVisual);
                ();
                control.Arrange((), content.RenderSize));
                visualTarget.RootVisual = control;

                System.Windows.Threading..Run();

            }));

            thread.SetApartmentState(.STA);
            thread.IsBackground = ;
            thread.Start();
        }

        
        {
             child;

             child)
            {
                )
                    );

                .child = child;
                AddVisualChild(child);
            }

             index)
            {
                ;
            }

             VisualChildrenCount
            {
                 1; }
            }
        }

    这个里面用来了两个新的类:HostVisual、VisualTarget。以及自己写的一个VisualHost。MSDN上相关的解释,也不算难理解,这里就不多介绍了。最后,再来重构一下代码,把在新线程中创建控件的方式改写如下:

     e)
        {
            createChildInNewThread<);
        }

         container) 
            ()
        {
            ();

            (hostVisual);
            container.Content = content;

            (() =>
            {
                (hostVisual);

                ();
                control.Arrange((), content.RenderSize));

                visualTarget.RootVisual = control;
                System.Windows.Threading..Run();

            }));

            thread.SetApartmentState(.STA);
            thread.IsBackground = ;
            thread.Start();
        }

    当然,我这个函数多了一些不必要的的限制:容器必须是ContentControl,子元素必须是UIElement。可以根据实际需要进行相关修改。

  • 相关阅读:
    09不可变类型
    08浅拷贝和深拷贝
    07参数的传递
    06判等对象是否相等
    05引用类型以及特殊引用类型string
    报错:Missing type map configuration or unsupported mapping
    黄聪:VS2010开发T4模版引擎之基础入门
    黄聪:《网站高转换率法则》#2:你的网站是垃圾站吗?
    黄聪:《网站高转换率法则》#1:为什么要研究网站转换率?
    黄聪:百度知道中对HTML字符实体、字符编号,&开头字符的使用
  • 原文地址:https://www.cnblogs.com/xietianjiao/p/11239332.html
Copyright © 2011-2022 走看看