首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >WPF优化UI线程的加载

WPF优化UI线程的加载
EN

Stack Overflow用户
提问于 2012-10-31 17:06:39
回答 4查看 2.1K关注 0票数 3

我试图优化我的WPF棱镜应用程序的加载时间。加载基本上是一个循环,使用反射创建UI元素的实例,然后将它们添加到选项卡控件中的主窗口( shell)。

由于我们仅限于使用单个线程来创建所有对象,那么加快加载/创建更好的用户体验的最佳方法是什么?

到目前为止,我有以下几种选择:

  1. 使用延迟加载。只有当用户第一次单击该选项卡时才加载该选项卡。但这将有4-5秒的延迟,第一次打开,因为它是根据需要初始化的。
  2. 缓存所有反射调用。我确实这么做了,但它并没有加速任何事情。大部分时间发生在控件的呈现过程中.

对于这个棘手的问题,任何建议都将不胜感激。

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2012-11-07 18:48:35

加速加载的最佳方法是在构建可视化树时简单地隐藏容器。

这防止了屏幕不断地需要自我更新。

当所有元素都添加到可视树中时,然后将容器可见性设置为visible,将选项卡容器呈现一次。

我们还实现了对选项卡控件项的一些简单的延迟呈现。

净结果:加载时间从2分钟下降到大约20秒。

票数 1
EN

Stack Overflow用户

发布于 2012-11-01 09:59:42

因为您只能在主线程上加载对象,所以我认为您不会让它加载得更快。

你能做的就是分散用户的注意力:我有一个动画片屏幕,需要10秒左右才能完成动画序列。这有若干目的:

  1. 它显示了用户的动作-所以他们有一个视觉提示,什么事情正在发生。
  2. 它分散了它们的注意力,并填补了初始负载所占用的空间。

为了确保动画流畅,您需要创建第二个dispatcher。我是这样做的:

代码语言:javascript
复制
public class AppEntry : Application
    {
        private static ManualResetEvent _resetSplashCreated;

        internal static Thread SplashThread { get; set; }

        internal static SplashWindow SplashWindow { get; set; }

        private static void ShowSplash()
        {
            SplashWindow = new SplashWindow();
            SplashWindow.Show();
            _resetSplashCreated.Set();
            Dispatcher.Run();
        }

        [STAThread]
        public static void Main()
        {
            _resetSplashCreated = new ManualResetEvent(false);
            SplashThread = new Thread(ShowSplash);
            SplashThread.SetApartmentState(ApartmentState.STA);
            SplashThread.IsBackground = true;
            SplashThread.Name = "Splash Screen";
            SplashThread.Start();

            _resetSplashCreated.WaitOne();

            var app = new App();
            app.DispatcherUnhandledException += new DispatcherUnhandledExceptionEventHandler(app_DispatcherUnhandledException);
            app.InitializeComponent();
            app.Run();

        }

        static void app_DispatcherUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e)
        {
           // MessageBox.Show(e.Exception.StackTrace);
        }
    }

我在Properties/Application选项卡中将AppEntry类设置为我的启动对象。

我在应用程序中的OnStartup方法的末尾关闭了我的启动屏幕:

代码语言:javascript
复制
 AppEntry.SplashWindow.Dispatcher.BeginInvoke(DispatcherPriority.Background,
                                                             new Action(() => AppEntry.SplashWindow.Close()));

这样更快吗?不,用户认为它更快吗?是

有时,如果你不能给他们速度,你可以给他们活动。很好的安慰剂。

票数 3
EN

Stack Overflow用户

发布于 2012-11-01 01:12:51

正如您提到的,如果您的对象是DependencyObjects,则不能使用多线程。肯特·布加特讨论了这一点。这就是为什么您必须利用INotifyPropertyChanged和POCO对象来保存您的数据。这样,您可以通过多线程获取数据,然后将这些数据绑定到您的UI中。使用DependencyObjects的另一个缺点是您过多地将应用程序绑定到WPF框架(DependencyObject是WPF程序集中的System.Windows命名空间中定义的类(不记得PresentationCore或PresentationFramework))。如果重构不是一种选择,那么您将不得不考虑一个类似于LastCoder提出的解决方案。请注意,您将能够完成非常少的多线程处理(如果有的话),因此您的应用程序不会一直都有很好的响应。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/13163173

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档