多线程,多调度程序WPF应用程序仍然在一个线程中绘制
本文关键字:一个 线程 绘制 调度程序 WPF 应用程序 多线程 | 更新日期: 2023-09-27 18:18:22
我有一个WPF &c#应用程序,包含一个大的数据网格,大约35栏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的画布,并绘制了一大堆GlyphRunDrawings - WPF在绘制这些东西时非常慢。
很遗憾,是的。也就是说,你可以做很多事情来提高ui的响应性。主要的事情之一是确保UI线程中完成的工作量最少。这意味着在一个单独的上下文中进行所有的DB读取等。您还应该研究您的网格是如何显示您的值的——它是虚拟化的吗?还有就是你是如何进行数据绑定的,一个绑定源应该允许你在所有的更改完成后才更新绑定。
如果使用得当,WPF是非常快的。
一些技巧:
- 实现要显示的数据的模型(或
MVVM
中的ViewModel)。确保它实现了INotifyPropertyChanged
接口。将这些模型的集合绑定到您的DataGrid
; - 不每N秒刷新所有数据。您应该以某种方式检测数据更改(使用工作线程)并在适当的模型上更新适当的属性。由于数据绑定,所有更改都将自动反映在DataGrid上。因此,您甚至不需要使用
Dispatcher
(至少显式地); - 如果您不需要对数据进行特殊操作(如编辑,排序,过滤等),请使用
ListView
代替DataGrid
; - 如果需要显示大量的行,可以考虑实现虚拟化。