【问题标题】:Preload WPF Window (perhaps in other thread) to improve performance预加载 WPF 窗口(可能在其他线程中)以提高性能
【发布时间】:2011-06-09 16:36:22
【问题描述】:

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

感谢您的帮助。

最好的问候,托马斯

【问题讨论】:

  • 如果确实是 Window 的图形导致它变慢(如果您在没有 ViewModel 的情况下仅创建并显示它会变慢吗?),您没有提供有关这些图形的信息任何人都可以帮助您使图形更轻,加载速度更快。

标签: c# wpf windows multithreading performance


【解决方案1】:

我有一个辅助 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

更改后,辅助窗口将在大约 10 毫秒内首次显示。起初我不喜欢冗余实例化的外观,但真的.. 有什么害处?还有很多其他事情可能会延迟新窗口的显示,但这当然值得一试。我是从this question 那里得到这个想法的。

【讨论】:

    【解决方案2】:

    当您创建 WPF 对象时——WindowUserControl 或任何其他从 DispatcherObject 派生的对象——它会将自身锁定到创建它的线程。所以你不能在后台线程中加载窗口,然后将其转移到主 UI 线程。如果您要在后台线程中创建它,它需要保留在该线程上;它需要由该线程显示,并在该线程上有一个消息泵。

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

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

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

    【讨论】:

      【解决方案3】:

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

      【讨论】:

        【解决方案4】:

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

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

        【讨论】:

        • GUI 元素需要时间来加载。还有其他解决方案可以实现我的目标吗?也许可以克隆一个窗口?
        • 你能给我们更多关于元素是什么的信息吗?实际上没有任何方法可以在 UI 线程之外创建 UI。 (这就是首先要有一个 UI 线程的意义......)
        • 不,WPF 不限于单一的 UI 线程。您通常只有一个 UI 线程,但这是一种约定,而不是内置限制。阅读 DispatcherObject 和 Dispatcher。
        【解决方案5】:

        如果我是你,我会从分析你的应用程序开始,看看在窗口启动期间真正需要什么时间。正如您被告知的那样,无法在其他线程中创建 GUI 并在主线程中使用它,但是如果您有任何统计数据,我们可以尝试找出可以并行或缓存的其他内容。

        【讨论】:

          【解决方案6】:

          留意塔拉斯所说的话。一般来说,winforms和wpf等技术在创建UI方面已经足够快了。当您看到缓慢的界面时,请仔细检查您自己的代码: 您是否正在加载数万行(然后使用分页)。 您是否在调用慢速方法(异步调用) 您是否多次调用数据库或网络? (打断电话或将它们放在另一个线程上)

          如果您在与上述列表类似的任何事情上都失败了,请回到您当前尝试做的事情。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2010-11-26
            • 1970-01-01
            • 2010-12-22
            • 2011-08-24
            • 2012-05-10
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多