TabItem 的异步首次加载的性能问题
当我加载 TabItem 时(每个 TabItem 都绑定到一个 ViewModel,每个 ViewModel 都有一个 DataTemplate),我的应用程序存在性能问题。为了解决这个问题,我在 ViewModel 构造函数中使用异步加载:
public MyViewModel(MyObject entity)
{
// WpfContext it's my Dispatcher
Task.Factory.StartNew(() => WpfContext.Invoke(() =>
{
//Initialisation
LoadMyObject(entity);
}));
}
使用这个解决方案,第一次加载 TabItem 时,需要一些时间,而且看起来并不是真正的异步。对于其他负载,它工作得很好并且是异步的。我不知道到底为什么。有什么建议吗?
I have a performance problem with my application, when I load a TabItem (each TabItem is bound to a ViewModel, each ViewModel having a DataTemplate). To solve this problem, I use an asynchronous loading in ViewModel constructor :
public MyViewModel(MyObject entity)
{
// WpfContext it's my Dispatcher
Task.Factory.StartNew(() => WpfContext.Invoke(() =>
{
//Initialisation
LoadMyObject(entity);
}));
}
With this solution, the first time the TabItem is loaded, it takes some times and seems not really asynchronous. For the other loads, it works good and asynchronously. I don't know exactly why. Any suggestion ?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
调度程序上的
Invoke
是对任务的后台线程和 UI 线程(一旦它决定实际运行代码)的阻塞调用。有时它看起来是异步的,因为 UI 线程正忙于显示新选项卡,因此后台线程的
Invoke
会阻塞,直到 UI 线程有时间处理它。当看起来像是同步时,UI 线程在显示新选项卡之前正在处理 Invoke 调用。所以,最后,我认为你有竞争条件。要解决此问题,您可能需要重构
LoadMyObject
方法,以便它可以在后台线程上运行,或者您可以使用 Dispatcher.BeginInvoke 方法并为其提供较低的优先级,以确保新选项卡的显示先于处理LoadMyObject
调用Invoke
on a Dispatcher is a blocking call for both the background thread of your Task and then also the UI thread (once it decides to actually run your code).It seems asynchronous sometimes because the UI thread is busy showing the new Tab, and so the
Invoke
from the background thread is blocking until the UI thread has time to process it. When it seems like it is synchronous, the Invoke call is being processed by the UI thread before the new Tab is being displayed. So, in the end, I think you have a race condition.To resolve this, you may need to refactor your
LoadMyObject
method so it can be run on the background thread, or you could use the Dispatcher.BeginInvoke method and provide it a lower priority to ensure the display of your new Tab precedes the processing of theLoadMyObject
call