ListView和DataGridView性能比较
来源:互联网 发布:知乎 非最大抑制 编辑:程序博客网 时间:2024/06/05 02:55
最近在写一个程序涉及列表控件的大量数据刷新,使用了ListView控件,但觉得逐条向ListView添加数据的方式性能不是很高,想改为数据绑定方式,网上搜索半天发现ListView不支持数据绑定,作罢,索性测试下ListView和DataGridView的性能。
性能测试静态类(负责测试耗时和内存占用)
public static class PerformanceMonitor
{
private static Stopwatch sw = new Stopwatch();
private static float duration = 0;
public static void StopwatchStart()
{
sw.Start();
}
public static void StopwatchStop()
{
sw.Stop();
duration = (float)sw.Elapsed.TotalSeconds;
}
public static void PrintStopwatchDuration()
{
Console.WriteLine(string.Format("耗时:{0}s", duration.ToString()));
}
public static double GetProcessUsedMemory()
{
double usedMemory = 0;
usedMemory = Process.GetCurrentProcess().WorkingSet64 / 1024.0 / 1024.0;
Console.WriteLine(string.Format("内存占用:{0}M", usedMemory.ToString()));
return usedMemory;
}
}
消息产生类(负责产生指定个数的消息)
public class Generator
{
private Thread generateMessageThread;//消息产生线程
private int count;//消息数目
public delegate void GenerateOneMessageEventHandler(string message);
public event GenerateOneMessageEventHandler GenerateOneMessageEvent;
public Generator()
{
count = 0;
}
public void StartGenerate(int num)
{
//产生num条消息
count = num;
generateMessageThread = new Thread(new ThreadStart(GenerateMessage));
generateMessageThread.IsBackground = true;
generateMessageThread.Start();
}
private void GenerateMessage()
{
PerformanceMonitor.StopwatchStart();//开始计时
string message = string.Empty;
for (int i = 0; i < count; i++)
{
message = "One Message";
if (GenerateOneMessageEvent != null)
{
GenerateOneMessageEvent(message);
}
}
PerformanceMonitor.StopwatchStop();//结束计时
PerformanceMonitor.PrintStopwatchDuration();//打印耗时
PerformanceMonitor.GetProcessUsedMemory();//打印内存占用
}
}
ListView控件逐条添加方式
Form类:
public partial class FormListView : Form
{
private int sequenceNumber;//列表序号
private ListViewItem lvi;//列表项
Generator messageGenerator1;//消息产生类,由事件触发列表的更新
private delegate void AppendMessageDelegate(string message);
public FormListView()
{
InitializeComponent();
listView.Columns.Add("序号");
listView.Columns.Add("消息");
sequenceNumber = 0;
messageGenerator1 = new Generator();
messageGenerator1.GenerateOneMessageEvent += new Generator.GenerateOneMessageEventHandler(AppendOneMessageToListView);
messageGenerator1.StartGenerate(1000);
}
public void AppendOneMessageToListView(string message)
{
if (listView.InvokeRequired)
{
AppendMessageDelegate del = new AppendMessageDelegate(AppendOneMessageToListView);
listView.Invoke(del, message);
return;
}
sequenceNumber++;
lvi = new ListViewItem(sequenceNumber.ToString());
lvi.SubItems.Add(message);
listView.Items.Add(lvi);
}
}
5次测试结果:
10条
100条
1000条
10000条
100000条
耗时(S)
< 0.1
< 0.5
3
30
380
内存占用(M)
23.04296875
23.43359375
24.52734375
29.71875
79.73828125
DataGridView逐条添加方式
Form类:
public partial class FormDataGridView : Form
{
private int sequenceNumber;//列表序号
Generator messageGenerator2;//消息产生类,由事件触发列表的更新
private delegate void AppendMessageDelegate(string message);
public FormDataGridView()
{
InitializeComponent();
dataGridView.Columns.Add("序号", "序号");
dataGridView.Columns.Add("消息", "消息");
messageGenerator2 = new Generator();
messageGenerator2.GenerateOneMessageEvent += new Generator.GenerateOneMessageEventHandler(AppendOneMessageToDataGridView);
messageGenerator2.StartGenerate(1000);
}
public void AppendOneMessageToDataGridView(string message)
{
if (dataGridView.InvokeRequired)
{
AppendMessageDelegate del = new AppendMessageDelegate(AppendOneMessageToDataGridView);
dataGridView.Invoke(del, message);
return;
}
sequenceNumber++;
dataGridView.Rows.Add(new object[] { sequenceNumber, message });
}
}
5次测试结果:
10条
100条
1000条
10000条
100000条
耗时(S)
< 0.1
< 0.3
1.3
17
550
内存占用(M)
23.6328125
24.3203125
24.91796875
30.140625
65.84375
DataGridView数据绑定方式(只负责绑定)
Form类:
public partial class FormDataGridView : Form
{
private int sequenceNumber;//列表序号
private DataTable messageTable;
Generator messageGenerator3;
public FormDataGridView()
{
InitializeComponent();
messageGenerator3 = new Generator3();
messageGenerator3.GenerateOneMessageEvent += new Generator.GenerateOneMessageEventHandler(AppendOneMessageToDataTable);
messageTable = new DataTable();
messageTable.Columns.Add("序号");
messageTable.Columns.Add("消息");
dataGridView.DataSource = messageTable;
messageGenerator3.StartGenerate(1000);
}
private void AppendOneMessageToDataTable(string message)
{
sequenceNumber++;
messageTable.Rows.Add(new object[] { sequenceNumber, message });
}
}
5次测试结果:
10条
100条
1000条
10000条
100000条
耗时(S)
< 0.01
0.7
5
56
…
内存占用(M)
23.3359375
25.87890625
26.359375
32.3671875
…
DataGridView数据绑定方式(定量/定时重绑定)
Form类:
public partial class FormDataGridView : Form
{
private int sequenceNumber;//列表序号
private DataTable messageTable;
private DataTable messageTableBuffer;
Generator messageGenerator4;
private delegate void ChangeDataSourceDelegate();
public FormDataGridView()
{
InitializeComponent();
messageGenerator4 = new Generator3();
messageGenerator4.GenerateOneMessageEvent += new Generator.GenerateOneMessageEventHandler(AppendOneMessageToDataTable);
messageTable = new DataTable();
messageTableBuffer = new DataTable();
messageTable.Columns.Add("序号");
messageTable.Columns.Add("消息");
messageGenerator3.StartGenerate(10000);
}
private void AppendOneMessageToDataTable(string message)
{
sequenceNumber++;
lock (messageTable)
{
messageTable.Rows.Add(new object[] { sequenceNumber, message });
if (sequenceNumber % 1000 == 0)
{
//1000条数据重绑定
ChangeDataSource();
}
}
}
public void ChangeDataSource()
{
if (dataGridView.InvokeRequired)
{
ChangeDataSourceDelegate del = new ChangeDataSourceDelegate(ChangeDataSource);
dataGridView.Invoke(del);
return;
}
dataGridView.DataSource = null;//解绑定
messageTableBuffer.Merge(messageTable.Copy());//将messageTable数据添加至messageTableBuffer
messageTable.Clear();//清除messageTable
dataGridView.DataSource = messageTableBuffer;//重绑定
}
}
3次测试结果:
1000条
10000条
100000条
耗时(S)
< 0.1
0.6
16
内存占用(M)
24.5078125
33.1484375
73.05859375
界面对比
总结
1、 直接向列表添加数据和绑定数据源两种方式的内存占用差距并不大;
2、 以直接向列表添加数据的方式,在数据量不大的情况下DataGridView占优,在大量数据时ListView的添加速度更快;但在实际使用中并不会频繁进行数据的添加,应该说这两种方式的差异不是很大;
3、 在使用DataGridView进行数据绑定后,若频繁地更新数据源,将会严重影响性能,原因应该是每次数据更新都会导致DataGridView发生重绘而降低性能,而当数据更新速度非常快时,甚至可能导致UI线程来不及绘制而发生错误;
4、 DataGridView的数据绑定适合大量数据的显示,而且这种方式也方便对数据进行修改,但不适合数据的频繁更新,故在数据频繁更新情况下,可采用重新绑定的方式,如上例4所示,首先开辟一个缓冲表,在一定量数据更新或者一定时间后重新绑定数据源,这样在性能上得到了明显的提升,远远好于其它三种方式,但缺点是牺牲了一定的内存空间;
5、 对于功能方面来说,DataGridView比ListView强大,不仅仅可以绑定各种数据源,还具有很多高级的功能,对于上面那种数据频繁更新的情况,可能有更好的解决方案,另外在界面方面,感觉ListView更美观些;
- ListView和DataGridView性能比较
- DataGridView和ListView比较
- DataGridView和ListView导出Excel
- ListView和datagridview的总结
- dataGridView 闪烁 和 listview 闪烁
- dataGridView 闪烁 和 listview 闪烁 的解决办法
- dataGridView 闪烁 和 listview 闪烁 的解决办法。
- dataGridView 闪烁 和 listview 闪烁 的解决办法
- dataGridView 闪烁 和 listview 闪烁 的解决办法
- ListView和RecyclerView比较
- ListView和RecycleView比较
- ListView和性能
- ListView 和RecyclerView的比较
- RecyclerView和listview的比较
- listview 和 recyclerview 的比较
- Excel数据导人到DataGridView和Excel数据导人到ListView
- C# 中DataGridView和ListView闪烁问题的解决方法
- 【性能】Java BigDecimal和double性能比较
- 计算机达人成长之路
- C++面试题
- FLASHxml
- 有趣的C语言问题 测试你对C语言的熟悉程度
- Android 资源国际化问题(2): finger的迷惑
- ListView和DataGridView性能比较
- C++的引用类型
- 今天是个好日子
- 如何取出Map中的key和value--Map.Entry 类使用简介
- SED单行脚本快速参考
- SystemParametersInfo 完整详细用法(转自Microsoft MSDN) 英文版,请自行翻译
- 关于windows系统的不满意,很慢,性能不好
- POJ1904/ZOJ2470 King's Quest(tarjan判强连通分量)
- 社交网络的大败局