在不阻塞的情况下将项目添加到 ObservableCollection<T> UI
Add items to ObservableCollection<T> without blocking UI
我正在尝试使用 SqlReader
从数据库 table 添加项目到 ObservableCollection<ProductSpecification>
。这是代码:
public void GetProductSpecification()
{
ProductSpecificationList.Clear();
using (var connect = Connection.Connect())
{
string query = "select * from ut_kst_specyfikacje_indeksow_test";
using (SqlCommand cmd = new SqlCommand(query, connect))
{
try
{
using (SqlDataReader reader = cmd.ExecuteReader())
{
while (reader.Read())
{
ProductSpecificationList.Add(new ProductSpecification()
{
//Here I am setting values of fields from reader[xx]. No parsing/converting errors in here.
//Also tried Dispatcher in here, but it throws exception "Invalid attempt to call MetaData while reader is closed"
});
}
}
}
catch (SqlException e)
{
NLogger.logger.Error(e.Message);
}
}
}
}
此方法在我绑定到按钮的 ICommand
命令之一中调用。当我点击这个按钮时,UI 冻结了大约 10 秒(ut_kst_specyfikacje_indeksow_test
中有 45 000 条记录)。在我看来它有点慢,老实说,我预计大约 2 秒。
据我所知,ObservableCollection
绑定到 UI 并且不能从 UI 线程以外的其他线程更新。我试过使用 Dispatcher
但出现异常:
Invalid attempt to call MetaData, while the reader is closed.
如何操作?
问题是您在 ObservableCollection
中每次添加时都会发出通知。这不适用于 45000 个项目
请注意,有很多解决方案,但是由于您每次都在清除它,因此只需创建一个新列表并一次性更新它。事实上,除非您想添加和删除项目,否则您甚至不需要 ObservableCollection
。但是,这里有一个一次性更新并更好地对待您的 UI
的示例
var list = new List<ProductSpecification>();
while (reader.Read())
{
list.Add(new ProductSpecification()
{
//Here I am setting values of fields from reader[xx]. No parsing/converting errors in here.
//Also tried Dispatcher in here, but it throws exception "Invalid attempt to call MetaData while reader is closed"
});
}
ProductSpecificationList = new ObservableCollection<ProductSpecification>(list);
注意:这是假设 ProductSpecificationList
引发了 属性 更改事件
也考虑制作全部 async Task
,并在 ExecuteReaderAsync
和类似
中使用 async
方法
加入胡椒粉和盐调味
我正在尝试使用 SqlReader
从数据库 table 添加项目到 ObservableCollection<ProductSpecification>
。这是代码:
public void GetProductSpecification()
{
ProductSpecificationList.Clear();
using (var connect = Connection.Connect())
{
string query = "select * from ut_kst_specyfikacje_indeksow_test";
using (SqlCommand cmd = new SqlCommand(query, connect))
{
try
{
using (SqlDataReader reader = cmd.ExecuteReader())
{
while (reader.Read())
{
ProductSpecificationList.Add(new ProductSpecification()
{
//Here I am setting values of fields from reader[xx]. No parsing/converting errors in here.
//Also tried Dispatcher in here, but it throws exception "Invalid attempt to call MetaData while reader is closed"
});
}
}
}
catch (SqlException e)
{
NLogger.logger.Error(e.Message);
}
}
}
}
此方法在我绑定到按钮的 ICommand
命令之一中调用。当我点击这个按钮时,UI 冻结了大约 10 秒(ut_kst_specyfikacje_indeksow_test
中有 45 000 条记录)。在我看来它有点慢,老实说,我预计大约 2 秒。
据我所知,ObservableCollection
绑定到 UI 并且不能从 UI 线程以外的其他线程更新。我试过使用 Dispatcher
但出现异常:
Invalid attempt to call MetaData, while the reader is closed.
如何操作?
问题是您在 ObservableCollection
中每次添加时都会发出通知。这不适用于 45000 个项目
请注意,有很多解决方案,但是由于您每次都在清除它,因此只需创建一个新列表并一次性更新它。事实上,除非您想添加和删除项目,否则您甚至不需要 ObservableCollection
。但是,这里有一个一次性更新并更好地对待您的 UI
var list = new List<ProductSpecification>();
while (reader.Read())
{
list.Add(new ProductSpecification()
{
//Here I am setting values of fields from reader[xx]. No parsing/converting errors in here.
//Also tried Dispatcher in here, but it throws exception "Invalid attempt to call MetaData while reader is closed"
});
}
ProductSpecificationList = new ObservableCollection<ProductSpecification>(list);
注意:这是假设 ProductSpecificationList
引发了 属性 更改事件
也考虑制作全部 async Task
,并在 ExecuteReaderAsync
和类似
async
方法
加入胡椒粉和盐调味