多线程,Multi-Dispatcher WPF应用程序仍然在单个线程中绘制?

时间:2011-12-17 20:22:04

标签: c# wpf multithreading performance

我有一个WPF& C#app包含一个大型DataGrid,大约35个cols x 50行,用于监视一堆频繁变化的值。问题是,当整个网格可见时,刷新它会挂起用户界面几乎一秒钟。我每隔两秒就明确刷新一次,这对我正在做的事情来说很好,但是让其余的UI挂起是一件非常痛苦的事。

好的,所以我决定在一个单独的线程中使用单独的Dispatcher在单独的窗口中运行UI的其余部分。我写了一个玩具窗口,其中只包含一个textBlock,其递增计数使用DispatcherTimer每秒更新10次。但是,不是计数顺利递增,而是在网格刷新时暂停,然后恢复显示,其计数比暂停时高出约10倍,因此计时器事件正在处理中。我只是没有看到刷新。

WPF是否只在一个线程中绘制所有元素?有什么方法吗?

这是我的第二个窗口创建代码:

private void Window_Loaded( object sender, RoutedEventArgs e )
{
    ThreadStart ts = new ThreadStart( RunSpareThread );
    m_spare_thread = new Thread( ts );
    m_spare_thread.IsBackground = true;
    m_spare_thread.Priority = ThreadPriority.Highest;
    m_spare_thread.SetApartmentState( ApartmentState.STA );
    m_spare_thread.Start();

    Dispatcher.Thread.Priority = ThreadPriority.Lowest;
}

void RunSpareThread()
{
    m_spare_window = new SpareWindow();
    m_spare_window.Show();
    Dispatcher.Run();
}

仅供参考我尝试以几种不同的方式实现网格 - 作为ListView,作为覆盖OnRender的Canvas并绘制一大堆GlyphRunDrawings - WPF在绘制这些内容时非常缓慢。

2 个答案:

答案 0 :(得分:3)

不幸的是,是的。也就是说,你可以做很多事情来提高你的ui的响应能力。其中一个主要方面是确保在UI线程中完成的工作量最少。这意味着在单独的上下文中完成所有数据库读取等操作。您还应该了解网格如何显示您的值 - 是否虚拟化?然后还有你是如何数据绑定的,绑定源应该允许你只在所有的更改完成后更新绑定。

答案 1 :(得分:1)

如果正确使用WPF,WPF会非常快。

一些提示:

  1. 实施您要显示的数据的模型(或MVVM的ViewModel)。确保它实现了INotifyPropertyChanged接口。将此类模型的集合绑定到DataGrid;
  2. 每N秒不刷新所有数据。您应该以某种方式检测数据更改(使用工作线程)并在适当的模型上更新适当的属性。由于数据绑定,所有更改都将自动反映在DataGrid上。因此,您甚至不需要使用Dispatcher(至少明确地);
  3. 如果您不需要对数据执行特殊操作(例如编辑,排序,过滤等),请使用ListView代替DataGrid;
  4. 如果需要显示大量行,请考虑实施virtualization