我有一个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没有显示这些对象。我尝试过使用静态硬编码集合并且工作正常 - 这是因为我的异步? 有人有建议吗?
- 感谢。
答案 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;
}