分享

ListView和DataGridView性能比较

 Cloud书屋 2012-12-19

最近在写一个程序涉及列表控件的大量数据刷新,使用了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更美观些;

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多