WPF使用异步方法更新ListBox中的itemssource

时间:2014-12-09 10:39:24

标签: c# wpf asynchronous listbox async-await

我有一个ListBox,并希望将其ItemsSource设置为我从云端获取的ObservableCollection。我必须等待这个传入的集合,这导致我的itemssource不能更新。

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

{
    InitializeComponent();
    GetEmployeeList();
}

它所谓的方法:

private async void GetEmployeeList()
{
    await EmployeeController.GetAllEmployees().ContinueWith(r =>
    {
        _employees = (r.Result);
        EmployeeListBox.ItemsSource = _employees;
    });
}

我的EmployeeController.GetAllEmployees()返回一个ObservableCollection。和_employees得到更新,但是我的EmployeeListBox没有显示这些对象。我尝试过使用静态硬编码集合并且工作正常 - 这是因为我的异步? 有人有建议吗?

- 感谢。

4 个答案:

答案 0 :(得分:2)

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

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

private async void GetEmployeeList()
{
   await EmployeeController.GetAllEmployees().ContinueWith(r =>
   {
       _employees = (r.Result);
       EmployeeListBox.ItemsSource = _employees;
   },
   TaskScheduler.FromCurrentSynchronizationContext());
}

但是,由于您正在使用await - 并且正在从UI线程调用,您也可以直接将await的结果设置为ItemSource:

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

...这也很好地证明了async / await关键字可以节省多少代码,而且还需要编写:)

答案 1 :(得分:0)

我认为你有一个“跨线程”的问题。 当您执行异步代码时,它在另一个线程中运行,并且此新线程无权访问UserInterface(UI),因为控件归用户界面线程所有。 解决方案是在可能的情况下轻轻地要求UI执行您的代码:

您必须使用Dispatcher。

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

        }), null);

有时,此类错误不可见。这就是难以诊断的问题。 您可以通过在为回调执行的代码周围添加Try...Catch来查看它。

致以最诚挚的问候,

答案 2 :(得分:0)

您可以将项目源用作IEnumerable,并为每个值使用yield return

答案 3 :(得分:0)

如果将await的结果存储在变量中然后分配它,则应避免使用跨线程。

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