预加载WPF窗口(可能在其他线程中)以提高性能

本文关键字:线程 高性能 其他 WPF 加载 窗口 | 更新日期: 2023-09-27 17:58:43

我有一个WPF窗口,它需要花费大量时间来创建和显示。用户应该能够打开一个或多个这样的窗口。现在,我正在寻找一种提高性能的方法。一个想法是在应用程序启动时(当它显示启动屏幕时)创建两个这样的窗口。之后,我只需要显示和隐藏这些窗口(并更改附加的视图模型)。这应该不是问题。但是,当用户使用应用程序时,他使用了在应用程序启动时加载的两个窗口,我应该在后台加载该窗口的第三个实例。现在,应用程序在加载第三个(或4。顺序5。等等)。现在,我正在寻找一种方法来做到这一点。是否可以在另一个线程中加载窗口,然后将其传输到主UI线程?或者还有其他场景可以达到目标?

谢谢你的帮助。

致以最良好的问候,Thomas

预加载WPF窗口(可能在其他线程中)以提高性能

我有一个第二个wpf窗口,第一次显示它需要很长时间(2秒)才能打开,而后续加载的时间很少。事实证明,这是由于正在加载扩展工具包程序集(以及其他几个程序集)。为了修复它,我在App.xaml.cs中添加了以下内容:

        var thread = new Thread(() =>
        {//Force runtime to pre-load all resources for secondary windows so they will load as fast as possible
            new SecondaryForm1();
            new SecondaryForm2();
        });
        thread.SetApartmentState(ApartmentState.STA);
        thread.Priority = ThreadPriority.Lowest;//We don't want prefetching to delay showing of primary window
        thread.Start();
        //Now start primary window

在这一变化之后,辅助窗口将在大约10ms内进行首次显示。一开始我不喜欢多余实例化的外观,但实际上。。有什么害处?还有很多其他因素可能会延迟新窗口的显示,但这当然值得一试。我是从这个问题中得到这个主意的。

当您创建一个WPF对象——Window、UserControl或从DispatcherObject派生的任何其他对象时,它会将自己锁定到创建它的线程。因此,您不能在后台线程中加载窗口,然后将其传输到主UI线程。如果你要在后台线程中创建它,它需要停留在该线程上;它需要由该线程显示,并且在该线程上有一个消息泵。

但这是可行的。你可以启动一个后台线程,在那里创建你的窗口,然后等待主线程说,"好吧,是时候显示窗口了"。然后你的线程可以调用ApplicationRun来启动它自己的消息泵,并在窗口关闭时关闭它自己。

当然,多线程会带来各种新的复杂性。您可能需要为每个窗口提供一个专用线程(线程池不太可能用于此)。您需要处理所有线程间的通信。如果窗口访问任何共享数据,您需要通过某种锁定来保护它。您需要确保应用程序在应该退出的时候退出(如果这意味着"当所有窗口都关闭时",那么您需要确保保护"打开的窗口数"资源)。可能还有其他并发症。不要轻易介入。

正如其他人所说,您最好的选择是评测您的代码,并尝试首先解决您的性能问题。但是,如果你确信你已经尽可能多地完成了性能工作,那么多线程和后台加载可能是一个值得探索的选择。

也许你试图从错误的方面解决问题?我认为您应该执行导致窗口挂起在后台的长时间操作,而不是尝试在后台运行窗口。您可以立即为用户显示窗口,然后显示一些不错的动画,而后台线程则通过检索数据/计算内容等来完成工作。也许我误解了你的问题

我认为这是不可能的,因为WPF应用程序只有一个UI线程。

是GUI元素需要一段时间才能加载,还是VM中的东西?如果它是虚拟机中的东西,您可以尝试在另一个线程上创建虚拟机,并将其引入…

如果我是你,我会从分析你的应用程序开始,看看在窗口启动过程中到底花了什么时间。正如您所知,没有办法在其他线程中创建GUI并在主线程中使用它,但如果您有任何统计数据,我们可以尝试找出哪些其他东西可以并行或缓存。

留意塔拉斯说了什么。一般来说,像winforms和wpf这样的技术在创建UI方面足够快。当您看到一个缓慢的界面时,请仔细检查您自己的代码:您是否加载了数以万计的行(然后使用分页)。你在调用一个慢方法吗(按时间顺序调用)你是否多次呼叫数据库或网络?(接听电话或将其放到另一个线程上)

如果你在类似于以上列表的任何事情上都失败了,请回到你目前尝试做的事情。