我在MySQL中有大量的数据,正好是10180行,而且它每天都在更新200-300行。在我的C#应用程序中,我有一个背景工作程序,它得到的数据和加载到一个datatable,然后这个datatable加载到一个ListView显示数据。
问题是这需要大约1分钟的时间,这在生产中太长了,我想解决这个问题并优化代码。
DoWork方法里面的代码。
try
{
connection.Close();
if (lvValidate.InvokeRequired)
{
lvValidate.BeginInvoke(new MethodInvoker(delegate
{
lvValidate.Items.Clear();
}));
}
else
{
lvValidate.Items.Clear();
}
System.Data.DataTable dt = DataTransferDA("SELECT * FROM workhours ORDER BY ID desc");
foreach (System.Data.DataRow row in dt.Rows)
{
ListViewItem tempLv = new ListViewItem(row["ID"].ToString());
tempLv.SubItems.Add(row["Date"].ToString());
tempLv.SubItems.Add(row["Name"].ToString());
tempLv.SubItems.Add(row["WorkCode"].ToString());
tempLv.SubItems.Add(row["Assembly"].ToString());
tempLv.SubItems.Add(row["Tech"].ToString());
tempLv.SubItems.Add(row["Beginning"].ToString());
tempLv.SubItems.Add(row["Ending"].ToString());
tempLv.SubItems.Add(row["Validated"].ToString());
tempLv.SubItems.Add(row["Validated name"].ToString());
lvValidate.BeginInvoke(new MethodInvoker(delegate
{
lvValidate.Items.Add(tempLv);
}));
}
if (lvValidate.InvokeRequired)
{
lvValidate.BeginInvoke(new MethodInvoker(delegate
{
lvValidate.TopItem = lvValidate.Items[topIndex];
}));
}
else
{
lvValidate.TopItem = lvValidate.Items[topIndex];
}
connection.Close();
}
catch (Exception ex) { MessageBox.Show("Error happened: " + ex.Message); connection.Close();} }
如果我不得不猜测它的列表视图是导致问题比数据大小。
我在一个有50284行的数据库上做了一个小测试。当我使用列表视图时,它花了很长时间才显示出来,我的笔记本风扇被踢到了全倾斜,即使通过数据迭代只花了876ms。 我把测试表单换成了一个基本的listbox,在构造函数中加载数据后,只花了几秒钟就显示出来了。
我使用EFCore来做数据连接处理,但我不能认为这造成了原始查询的性能的巨大变化。
数据(50284)花了876
int i = 0;
using (EFContext ctx = new EFContext())
{
foreach(data dt in ctx.data.AsNoTracking())
{
i++;
listBox.Items.Add(dt.epc);
}
}
watch.Stop();
System.Diagnostics.Debug.WriteLine($"Data({i}) took {watch.ElapsedMilliseconds}");
编辑]EFContext是一个Entity Framework Core组件,但它所做的只是包裹数据库模型。 我追踪了一下,它只是和你一样发出了一个select blah from db.table。它只是把数据以类的形式保存下来,所以你可以像正常的代码一样进行迭代和交互。
我目前是在Entity Framework模式下,并且有这个测试所需的所有模拟代码,否则我会做一个基本的SQL连接。 在这个问题上,查看器是问题,而不是数据大小。
一些建议
对datarow使用整数索引。整数索引可以是 快3-4倍. 在你的循环中,你每行要查找10次列的索引,在循环外查找一次列的位置,然后在循环内使用整数索引。在循环外查找一次列的位置,然后在循环内使用整数索引。
intDateCol = dt.Columns.IndexOf("Date");...SubItems.Add(row[intDateCol])。
在清除项目并添加它们之前使用ListView.BeginUpdate(),然后在完成后调用ListView.EndUpdate()。
如果你仍然有性能问题,请尝试在你的应用程序中使用ListView.BeginUpdate()。虚拟模式.
有一个深入的看ListView的性能调整。此处