C# 等待ListBox完成呈现WPF

C# 等待ListBox完成呈现WPF,c#,wpf,C#,Wpf,我有一个observateCollection(),出于测试目的,我有一个简单的for循环,它添加了2000000条随机数的记录进行搜索。当我点击加载客户时,这显示了一个很好的微调器,工作正常 private async void button_Click(object sender, RoutedEventArgs e) { bool result = DatabaseMaster.CheckConnection(con); spinner.Visib

我有一个
observateCollection()
,出于测试目的,我有一个简单的for循环,它添加了2000000条随机数的记录进行搜索。当我点击加载客户时,这显示了一个很好的微调器,工作正常

private async void button_Click(object sender, RoutedEventArgs e)
    {

        bool result = DatabaseMaster.CheckConnection(con);
        spinner.Visibility = Visibility.Visible;
        spinner.Spin = true;
        customers = await Task.Run(()=>DatabaseMaster.GetCustomers());
        customerListBox.ItemsSource = customers;
        spinner.Visibility = Visibility.Collapsed;
        spinner.Spin = false;
    }
但是,我有一个用于搜索的文本框,希望搜索客户并更新视图。我试过了

wait Task.Run(()=>customerListBox.ItemsSource=customers.Where(X=>X.name.ToLower().Contains(searchTextBox.Text.ToLower()))

但是,由于调用线程出错,该线程无法访问该对象,因为它是由另一个线程拥有的

我尝试了这个方法,但是UI在更新项目源时仍然会跳转。有什么想法或者我应该了解更多关于inotifypropertychanged的信息吗

private async void search_TextChanged(object sender, TextChangedEventArgs e)
    {
        spinner.Visibility = Visibility.Visible;
        spinner.Spin = true;
        customerListBox.Background = Brushes.Gray;
        customerListBox.IsEnabled = false;
        await this.Dispatcher.BeginInvoke(new Action(() =>
         {
             customerListBox.ItemsSource = customers.Where(X => X.name.ToLower().Contains(searchTextBox.Text.ToLower()));
         }), null);
        customerListBox.Background = Brushes.White;
        customerListBox.IsEnabled = true;
        spinner.Visibility = Visibility.Collapsed;
        spinner.Spin = false;
    }

看起来
客户
只是一个本地收藏。通常在另一个线程中查询它没有什么意义。但是,如果您仍然需要它,请确保仅从UI线程使用UI对象(
customerListBox


若您将代码更改为以下代码,那个么它应该可以工作(因为itemsource将在ui线程中分配,而不是在任务内部分配)

customerListBox.ItemsSource = await Task.Run(()=> customers.Where(X => X.name.ToLower().Contains(searchTextBox.Text.ToLower())));

在后台任务中执行
Where
,只更新ui线程中的
ItemsSource
。当有太多条目时,它仍然会闪烁。请注意,
.Where(…)
实际上没有做那么多。如果要在任务中进行计算,需要调用
.Where(…).ToList()
@grek40当我在文本框中键入内容时,它仍然会冻结,因为当它冻结时,它甚至不会显示我的微调器?如果你有那么多记录,为什么不直接使用
虚拟化StackPanel
?@XAMIMAX我目前没有那么多记录,但希望它能经得起未来的考验,实际上它可能不会超过20000条rning和将取决于备选方案。当我添加此选项时,UI仍会冻结,它会冻结约4秒,然后响应。我相信是这一行
customerListBox.ItemsSource=r;
导致了problem@bish25您可能在没有
ToList()的情况下尝试了第一个版本
。当我尝试获取错误时,请尝试当前的一个。
调用线程无法访问此对象,因为另一个线程拥有它。什么类型的
客户
?问题可能还有第二个部分……读取任务中的
搜索文本框。文本
。我不确定。它仍然会冻结约3秒钟,但它没有甚至没有在ui线程上显示我的微调器,这让我相信是ui本身减慢了速度
customerListBox.ItemsSource = await Task.Run(()=> customers.Where(X => X.name.ToLower().Contains(searchTextBox.Text.ToLower())));