【发布时间】:2013-01-07 04:59:31
【问题描述】:
我有一个自定义对象 (MyObject),它实现了 INotifyPropertyChanged 并具有三个属性(一个 int、一个 string 和一个 bool)。这是该对象的代码:
public class MyObject : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(PropertyChangedEventArgs e)
{
if (PropertyChanged != null)
{
PropertyChanged(this, e);
}
}
private int _Index;
public int Index
{
get { return _Index; }
set
{
if (_Index == value)
{
return;
}
_Index = value;
OnPropertyChanged(new PropertyChangedEventArgs("Index"));
}
}
private string _Name;
public string Name
{
get { return _Name; }
set
{
if (_Name == value)
{
return;
}
_Name = value;
_Modified = true;
OnPropertyChanged(new PropertyChangedEventArgs("Name"));
}
}
private bool _Modified;
public bool Modified
{
get { return _Modified; }
set
{
if (_Modified == value)
{
return;
}
_Modified = value;
OnPropertyChanged(new PropertyChangedEventArgs("Modified"));
}
}
public MyObject()
{
}
public MyObject(int index, string number, bool modified)
{
Index = index;
Number = number;
Modified = modified;
}
}
长话短说,我将这些对象的 BindingList 连接到 DataGridView,如下所示:
BindingList<MyObject> myObjectList = new BindingList<MyObject>();
BindingSource bindingSourceForMyObjects = new BindingSource();
bindingSourceForMyObjects.DataSource = myObjectList;
dataGridViewMyObjects.DataSource = bindingSourceForMyObjects;
当我的应用程序运行时,myObjectList 将填充 100,000 个对象(从文件中读取)并显示在我的 DataGridView 中。我在 DataGridView 中只有一列,它显示我的对象的字符串属性。我的用户可能想要选择 DataGridView 中的所有行并“删除”它们。我在删除术语周围使用引号,因为对象实际上并没有被删除,而是所有 100,000 个对象的字符串属性都设置为 string.Empty。现在,我使用以下代码执行该操作:
myObjectList.ToList().ForEach(c => c.Name = string.Empty);
此操作大约需要 55 秒才能完成。我也试过:
foreach (DataGridViewRow row in dataGridViewMyObjects.SelectedRows)
{
row.Cells["NAME"].Value = string.Empty;
}
这需要的时间略短,为 49 秒,但仍然是一个很长的操作。另外,我还为 bindingSourceForMyObjects 定义了一个 ListChanged 事件处理程序,如下所示:
private void bindingSourceForMyObjects_ListChanged(object sender, ListChangedEventArgs e)
{
if (e.ListChangedType == ListChangedType.ItemChanged)
{
dataGridViewMyObjects.Rows[e.NewIndex].DefaultCellStyle.BackColor = Color.Red;
dataGridViewMyObjects.Rows[e.NewIndex].DefaultCellStyle.ForeColor = Color.White;
}
}
如您所见,当我以编程方式更改基础对象列表时,我使用它来直观地指示 DataGridView 中已更改的行(就像我将它们全部设置为 string.Empty 时所做的那样)。当我“删除”所有对象时,这确实会增加一些开销,但即使没有这个事件处理程序,它仍然是一个冗长的操作。
最后,我的 WinForms 应用程序目前是单线程的,但我计划编写多线程代码,这样做是有意义的。这个操作可能是其中一种情况,但在我走这条路之前,还有什么我遗漏的(或者我不需要做的事情)可以提高这个操作的性能,所以它不会几乎需要一分钟才能完成?或者这只是处理 100,000 个对象的本质?
【问题讨论】:
-
你能区分在
.ToList()中花费的时间与在.ForEach(c => ...)中花费的时间吗? -
c.Name属性是否在其设置器中执行任何操作或只是一个自动属性? -
.ToList() 需要
-
控制台应用程序中的 for-loop 性能是否相似(即,在 gui 之外)?
-
你能发布你的代码来实现
INotifyPropertyChanged吗?你是从哪里发起活动的?我刚刚使用上面的代码做了一个快速测试,我可以在几秒钟内更新大约 250k 行。INotifyPropertyChanged实现可能会导致速度变慢。
标签: c# winforms multithreading datagridview