在不阻塞的情况下将项目添加到 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 方法

加入胡椒粉和盐调味