目录
一. 高刷错误方法:每更新一次数据,就数据驱动刷新datagird
2. UI下面的cs文件实现数据绑定(没有用ViewModel)
二. 高刷改进方法:每更新一次数据,将数据选择性的放入队列,另外一个线程队列数据驱动刷新datagird
1. MainWindowViewModel.cs里面的绑定显示数据,和数据容器定义
2. 每秒最多把N个数据放入数据容器,同时需要把每秒的最后一次更新数据放入容器
一. 高刷错误方法:每更新一次数据,就数据驱动刷新datagird
两个datagrid控件,直接用线程刷新,具体实现如下:
1. UI矢量语言实现
< 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" />
</ DataGrid.Columns >
</ DataGrid >
</ Border >
< 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" />
</ DataGrid.Columns >
</ DataGrid >
</ Border >
2. UI下面的cs文件实现数据绑定(没有用ViewModel)
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();
}
});
}
/// <summary>
/// 更新Ui1
/// </summary>
/// <param name=""></param>
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)
{
}
}
/// <summary>
/// 更新Ui2
/// </summary>
/// <param name=""></param>
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)
{
}
}
3. 运行结果及分析
运行5分钟后的内存占用情况
现状:
两个datagrid每秒刷新1000/2=200次/秒,界面相应迟钝,内存200M;五分钟左右涨到了2000M+,肉眼可见的刷新频率明显只有5次/秒,再继续没时间不测试了意义不大
原因分析:
数据更新太快,被堆积了的大量消息(BeginInvoke),造成了内存增加,界面相应变慢
对策:
一般的显示器刷新频率60或75HZ,数据刷新的太快了,屏幕显示不过来,就是显示过来了,眼睛也看不清,所以我们只需要把刷新频率限制到10次/秒,即可解决问题
待继续…
————————————————————————————————————————-
二. 高刷改进方法:每更新一次数据,将数据
选择性
的放入队列,另外一个线程队列数据驱动刷新datagird
1.
MainWindowViewModel.cs里面的绑定显示数据,和数据容器定义
//工具显示绑定数据
private ObservableCollection<DispVara> _moduleVaraList = new ObservableCollection<DispVara>();
public ObservableCollection<DispVara> ModuleVaraList
{
get
{
return _moduleVaraList;
}
set
{
_moduleVaraList = value;
OnPropertyChanged("ModuleVaraList");
}
}
//工具显示绑定数据
private ObservableCollection<DispVara> _moduleVaraList2 = new ObservableCollection<DispVara>();
public ObservableCollection<DispVara> ModuleVaraList2
{
get
{
return _moduleVaraList2;
}
set
{
_moduleVaraList2 = value;
OnPropertyChanged("ModuleVaraList2");
}
}
//工具显示数据容器,每秒钟只再容器中放入10个数据
private Queue<List<DispVara>> _moduleVaraContainer = new Queue<List<DispVara>>();
public Queue<List<DispVara>> ModuleVaraListContainer
{
get
{
return _moduleVaraContainer;
}
set
{
_moduleVaraContainer = value;
}
}
//工具显示数据容器,每秒钟只再容器中放入10个数据
private Queue<List<DispVara>> _moduleVaraContainer2 = new Queue<List<DispVara>>();
public Queue<List<DispVara>> ModuleVaraListContainer2
{
get
{
return _moduleVaraContainer2;
}
set
{
_moduleVaraContainer2 = value;
}
}
2. 每秒最多把N个数据放入数据容器,
同时需要把每秒的最后一次
更新数据放入容器
/// <summary>
/// 更新Ui容器
/// </summary>
/// <param name=""></param>
private void UpdateUiContainer()
{
try
{
Random random = new Random();
List<DispVara> temp = new List<DispVara>();
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<DispVara>(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<DispVara>(temp);
}
else if ((temp[0].GenerateTime - _lastDispVara[0].GenerateTime).Seconds == 1)//每秒的最后一次更新,需要加到显示容器
{
ModuleVaraListContainer.Enqueue(_lastDispVara);
ModuleVaraListContainer.Enqueue(temp);
_lastDispVara.Clear();
_lastDispVara = new List<DispVara>(temp);
}
else
{
//放弃显示
}
}
}
}
catch (Exception ex)
{
}
}
效果视频如下:
datagird通过数据容器刷新
三. 源码链接
(19条消息) Wpfdatagrid高刷问题解决方案-C#文档类资源-CSDN文库
参考资料: