目录
一. 高刷错误方法:每更新一次数据,就数据驱动刷新datagird
1. UI矢量语言实现
2. UI下面的cs文件实现数据绑定(没有用ViewModel)
3. 运行结果及分析
二. 高刷改进方法:每更新一次数据,将数据选择性的放入队列,另外一个线程队列数据驱动刷新datagird
1. MainWindowViewModel.cs里面的绑定显示数据,和数据容器定义
2. 每秒最多把N个数据放入数据容器,同时需要把每秒的最后一次更新数据放入容器
三. 源码链接
两个datagrid控件,直接用线程刷新,具体实现如下:
< Border
Grid.Row = "0"
Height = "Auto"
HorizontalAlignment = "Stretch"
VerticalAlignment = "Stretch"
Background = "AliceBlue" >
< DataGrid
x: Name = "dg_ModuleVara"
Height = "200"
HorizontalAlignment = "Stretch"
VerticalAlignment = "Stretch"
AutoGenerateColumns = "false"
Background = "{StaticResource PrimaryBlackBrush}"
BorderBrush = "{StaticResource BoxBackgroundBrush}"
BorderThickness = "1"
CanUserAddRows = "False"
CanUserSortColumns = "False"
ColumnWidth = "*"
GridLinesVisibility = "All"
HorizontalGridLinesBrush = "{StaticResource BoxBackgroundBrush}"
HorizontalScrollBarVisibility = "Hidden"
RowBackground = "{StaticResource PrimaryBlackBrush}"
RowHeaderWidth = "0"
SelectionUnit = "FullRow"
VerticalGridLinesBrush = "{StaticResource BoxBackgroundBrush}"
VerticalScrollBarVisibility = "Hidden" >
< DataGrid.Columns >
< DataGridTextColumn
Width = "1*"
Binding = "{Binding Name, Mode=OneWay}"
Foreground = "White"
IsReadOnly = "True" />
< DataGridTextColumn
Width = "1*"
Binding = "{Binding DispValue, Mode=OneWay}"
Foreground = "White"
IsReadOnly = "True" />
< Border
Grid.Row = "1"
Height = "Auto"
HorizontalAlignment = "Stretch"
VerticalAlignment = "Stretch"
Background = "AliceBlue" >
< DataGrid
x: Name = "dg_ModuleVara2"
HorizontalAlignment = "Stretch"
VerticalAlignment = "Stretch"
AutoGenerateColumns = "false"
Background = "{StaticResource PrimaryBlackBrush}"
BorderBrush = "{StaticResource BoxBackgroundBrush}"
BorderThickness = "1"
CanUserAddRows = "False"
CanUserSortColumns = "False"
ColumnWidth = "*"
GridLinesVisibility = "All"
HorizontalGridLinesBrush = "{StaticResource BoxBackgroundBrush}"
HorizontalScrollBarVisibility = "Hidden"
RowBackground = "{StaticResource PrimaryBlackBrush}"
RowHeaderWidth = "0"
SelectionUnit = "FullRow"
VerticalGridLinesBrush = "{StaticResource BoxBackgroundBrush}"
VerticalScrollBarVisibility = "Hidden" >
< DataGrid.Columns >
< DataGridTextColumn
Width = "1*"
Binding = "{Binding Name, Mode=OneWay}"
Foreground = "White"
IsReadOnly = "True" />
< DataGridTextColumn
Width = "1*"
Binding = "{Binding DispValue, Mode=OneWay}"
Foreground = "White"
IsReadOnly = "True" />
public MainWindow()
{
InitializeComponent();
dg_ModuleVara.ItemsSource = null;
dg_ModuleVara.ItemsSource = ModuleVaraList;
dg_ModuleVara2.ItemsSource = null;
dg_ModuleVara2.ItemsSource = ModuleVaraList2;
Task.Run(() =>
{
while (true)
{
UpdateUiTool();
UpdateUiTool2();
Task.Delay(5).Wait();
}
});
}
///
/// 更新Ui1
///
///
private void UpdateUiTool()
{
try
{
Random random = new Random();
System.Windows.Application.Current.Dispatcher.BeginInvoke(new Action(() =>
{
ModuleVaraList.Clear();
for (int imm = 0; imm < 10; imm++)
{
DispVara dispVara = new DispVara() { Name = $"标题{imm.ToString()}-{random.NextDouble()}", DispValue = $"内容{imm.ToString()}-{random.NextDouble()}" };
ModuleVaraList.Add(dispVara);
}
}));
}
catch (Exception ex)
{
}
}
///
/// 更新Ui2
///
///
private void UpdateUiTool2()
{
try
{
Random random = new Random();
System.Windows.Application.Current.Dispatcher.BeginInvoke(new Action(() =>
{
ModuleVaraList2.Clear();
for (int imm = 0; imm < 10; imm++)
{
DispVara dispVara = new DispVara() { Name = $"标题{imm.ToString()}-{random.NextDouble()}", DispValue = $"内容{imm.ToString()}-{random.NextDouble()}" };
ModuleVaraList2.Add(dispVara);
}
}));
}
catch (Exception ex)
{
}
}
运行5分钟后的内存占用情况
现状:两个datagrid每秒刷新1000/2=200次/秒,界面相应迟钝,内存200M;五分钟左右涨到了2000M+,肉眼可见的刷新频率明显只有5次/秒,再继续没时间不测试了意义不大
原因分析:数据更新太快,被堆积了的大量消息(BeginInvoke),造成了内存增加,界面相应变慢
对策:一般的显示器刷新频率60或75HZ,数据刷新的太快了,屏幕显示不过来,就是显示过来了,眼睛也看不清,所以我们只需要把刷新频率限制到10次/秒,即可解决问题
待继续...
-------------------------------------------------------------------------------------------------------------------------
//工具显示绑定数据
private ObservableCollection _moduleVaraList = new ObservableCollection();
public ObservableCollection ModuleVaraList
{
get
{
return _moduleVaraList;
}
set
{
_moduleVaraList = value;
OnPropertyChanged("ModuleVaraList");
}
}
//工具显示绑定数据
private ObservableCollection _moduleVaraList2 = new ObservableCollection();
public ObservableCollection ModuleVaraList2
{
get
{
return _moduleVaraList2;
}
set
{
_moduleVaraList2 = value;
OnPropertyChanged("ModuleVaraList2");
}
}
//工具显示数据容器,每秒钟只再容器中放入10个数据
private Queue> _moduleVaraContainer = new Queue>();
public Queue> ModuleVaraListContainer
{
get
{
return _moduleVaraContainer;
}
set
{
_moduleVaraContainer = value;
}
}
//工具显示数据容器,每秒钟只再容器中放入10个数据
private Queue> _moduleVaraContainer2 = new Queue>();
public Queue> ModuleVaraListContainer2
{
get
{
return _moduleVaraContainer2;
}
set
{
_moduleVaraContainer2 = value;
}
}
///
/// 更新Ui容器
///
///
private void UpdateUiContainer()
{
try
{
Random random = new Random();
List temp = new List();
for (int imm = 0; imm < 10; imm++)
{
DispVara dispVara = new DispVara() { Name = $"标题{imm.ToString()}-{random.NextDouble()}", DispValue = $"内容{imm.ToString()}-{random.NextDouble()}", GenerateTime = DateTime.Now };
temp.Add(dispVara);
}
if (ModuleVaraListContainer.Count == 0 && _lastDispVara.Count == 0)
{
if (temp.Count > 0)
{
_lastDispVara = new List(temp);
ModuleVaraListContainer.Enqueue(temp);
}
}
else
{
if(temp.Count > 0)
{
if((temp[0].GenerateTime - _lastDispVara[0].GenerateTime).TotalMilliseconds >= 1000.0 / (_showTimesMaxSencond*1.0))
{
ModuleVaraListContainer.Enqueue(temp);
_lastDispVara.Clear();
_lastDispVara = new List(temp);
}
else if ((temp[0].GenerateTime - _lastDispVara[0].GenerateTime).Seconds == 1)//每秒的最后一次更新,需要加到显示容器
{
ModuleVaraListContainer.Enqueue(_lastDispVara);
ModuleVaraListContainer.Enqueue(temp);
_lastDispVara.Clear();
_lastDispVara = new List(temp);
}
else
{
//放弃显示
}
}
}
}
catch (Exception ex)
{
}
}
效果视频如下:
datagird通过数据容器刷新
(19条消息) Wpfdatagrid高刷问题解决方案-C#文档类资源-CSDN文库
参考资料:
WPF绘制图表时,1ms更新一次数据,界面变得特别卡? - 知乎 (zhihu.com)
wpf datagrid卡顿是什么原因? - 知乎 (zhihu.com)