2011-06-09 125 views
3

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

感谢您的任何帮助。

最好的问候,托马斯

+0

如果它确实是窗口的图形导致它变慢(如果您创建并仅显示没有ViewModel的话,速度会变慢吗?),您没有提供关于这些图形的任何人的信息以帮助您使图形更轻,更快加载。 – 2011-06-09 19:51:44

回答

5

当您创建WPF对象 - Window,UserControl或其他任何从DispatcherObject下降的东西时 - 它将自己锁定到创建它的线程。所以你不能在后台线程中加载窗口,然后将其转移到主UI线程。如果你打算在后台线程中创建它,它需要停留在该线程上;它需要由该线程显示,并在该线程上具有消息泵。

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

当然,多线程打开了各种新的复杂问题。您可能需要为每个窗口设置一个专用线程(线程池不太可能用于此目的)。你需要处理所有的线程间通信。如果窗口访问任何共享数据,则需要使用某种锁定来保护它。您需要确保应用程序退出时(如果这意味着“当所有窗口关闭”时,则需要确保您保护“打开窗口的计数”资源)。也可能有其他复杂情况。不要轻视这一点。

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

1

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

难道是服用一段时间来加载的GUI元素,或者在虚拟机的东西?如果它的东西,在虚拟机,你可以尝试在另一个线程创建VM和把它...

+1

GUI元素正在花时间加载。有其他解决方案来达到我的目标吗?也许可以克隆一个窗口? – BennoDual 2011-06-09 16:45:19

+0

你能给我们提供更多关于元素的信息吗?没有任何方法可以从UI线程创建UI。 (这就好比在第一个UI线程中......) – 2011-06-09 17:05:59

+1

不,WPF不限于一个且只有一个UI线程。你*通常*只有一个UI线程,但这是一个约定,而不是内置的限制。阅读DispatcherObject和Dispatcher。 – 2011-06-09 21:02:07

4

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

1

如果我是你,我会从剖析应用程序,看看什么是真正采取窗口开始时准时开始。正如你所知道的,在其他线程中没有办法创建GUI,然后在主线程中使用它,但是如果你有任何统计信息,我们可以尝试找出可以并行或缓存的其他东西。

1

保持在什么塔拉斯说眼睛。一般来说,winforms和wpf等技术在创建UI时足够快。当你看到一个缓慢的界面时,仔细检查你自己的代码: 你是否加载了成千上万的行(然后使用分页)。 您是否正在调用缓慢的方法(如同步调用它) 您是否正在对数据库或网络进行多次调用? (巴赫的呼叫或把它们放在另一个线程)

回来给你目前尝试,如果你失败了,在任何类似上述名单做。

5

我有一个第二个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左右。起初我不喜欢冗余实例的外观,但真的......有什么危害?还有很多其他的东西可能会延迟显示新窗口,但这当然值得一试。我从this question得到了这个想法。