C# WPF使用异步方法更新列表框中的itemssource

C# WPF使用异步方法更新列表框中的itemssource,c#,wpf,asynchronous,listbox,async-await,C#,Wpf,Asynchronous,Listbox,Async Await,我有一个列表框,希望将其ItemsSource设置为我从云中获取的可观察集合。我必须等待此传入集合,它导致我的itemssource无法更新 这是我的方法。 这是我的xaml.cs构造函数: { InitializeComponent(); GetEmployeeList(); } 以及它调用的方法: private async void GetEmployeeList() { await EmployeeController.GetAllEmployees().Con

我有一个列表框,希望将其ItemsSource设置为我从云中获取的可观察集合。我必须等待此传入集合,它导致我的itemssource无法更新

这是我的方法。 这是我的xaml.cs构造函数:

{
    InitializeComponent();
    GetEmployeeList();
}
以及它调用的方法:

private async void GetEmployeeList()
{
    await EmployeeController.GetAllEmployees().ContinueWith(r =>
    {
        _employees = (r.Result);
        EmployeeListBox.ItemsSource = _employees;
    });
}
My EmployeeController.GetAllEmployees()返回一个ObservableCollection。而且_EmployeeListBox会更新,但是我的EmployeeListBox不会显示这些对象。我试过使用静态硬编码集合,但效果很好——这是因为我的异步吗? 有人有什么建议吗

- 谢谢。

我想你有一个“交叉线程”问题。 当您执行异步代码时,它会在另一个线程中运行,而这个新线程没有访问用户界面(UI)的权限,因为控件属于用户界面线程。 解决方案是在可能的情况下,温和地要求UI执行代码:

你必须使用调度器

    this.Dispatcher.BeginInvoke(new Action(() =>
        {
            // - Change your UI information here

        }), null);
有时,这种类型的错误是不可见的。这就是很难诊断的原因。 您可以通过在为回调执行的代码周围添加
Try…Catch
来查看它


请注意,

您可以将项目源用作IEnumerable,并对每个值使用收益率返回值

假设您确定正在调用continueWith,那么您的continueWith代码块很可能发生在none UI线程上

一个选项是为延续设置CurrentSyncronizationContext(下面的示例)。这将要求继续代码在启动原始任务的同一线程上执行。或者,您需要在UI线程上调用代码,最常用的方法是使用Dispatcher

private async void GetEmployeeList()
{
   await EmployeeController.GetAllEmployees().ContinueWith(r =>
   {
       _employees = (r.Result);
       EmployeeListBox.ItemsSource = _employees;
   },
   TaskScheduler.FromCurrentSynchronizationContext());
}
但是,由于您使用的是等待,并且是从UI线程调用的,因此您也可以将等待的结果设置为ItemSource direct:

private async void GetEmployeeList()
{
   EmployeeListBox.ItemsSource = await EmployeeController.GetAllEmployees();
}

。。。这也很好地演示了async/await关键字为您节省了编写代码的时间:)

如果您将等待的结果存储在一个变量中,然后分配它,您应该避免交叉线程

private async void GetEmployeeList()
{
    var emps = await EmployeeController.GetAllEmployees();
    EmployeeListBox.ItemsSource = _emps;
}

调用
async
方法不会导致在另一个线程中调用它。您将TPL之类的东西与async/await混淆了。@DanielKelley:我认为任何async/await操作都会在另一个线程上调用其回调,请参阅Olite answer,其中也谈到了非UI线程。MS编写的async/await只是语法上的糖类。我们看到一个简单的“Thread.Timer”在另一个线程中引发了“appeased”。很抱歉,我们的评论太晚了,我们遇到了服务器问题。但我们终于能够测试这个,它就像一个符咒。谢谢