我有以下ViewModel结构:
我通过以下代码在MainViewModel和DetailViewModel之间导航:
navigationService.For<DetailViewModel>().Navigate();
它是DetailViewModel的构造函数:
public DetailViewModel(INavigationService navigationService)
{
GetData();
}
private async Task GetData()
{
using (var context = new MyDataContext())
{
var result = await (from data in context.Data
select data).ToListAsync();
DataList = new ObservableCollection<Data>(result);
}
}
由于我在调用await
时不使用GetData
,构造函数应该非常快速地返回,并且应该在以后填充列表。
我遇到非常慢的导航,我点击了MainViewModel中的项目,GUI冻结了一秒钟,当填充列表时,我看到了详细信息(debug显示构造函数在列表完成之前完成。)
我看到一个警告说:
因为没有等待此调用,所以执行当前方法 在通话完成之前继续。
然后阻止什么?我还应该设置什么?
答案 0 :(得分:2)
AFAIK,SQLite实体框架提供程序不支持真正的异步方法。因此,对JPA
的调用实际上是同步的,导致您的延迟。
解决此问题的最佳方法是将ToListAsync
与Task.Run
一起使用(不 await
或ContinueWith
):
Execute.OnUIThread
请注意引入public DetailViewModel(INavigationService navigationService)
{
InitializeAsync();
}
private async Task InitializeAsync()
{
try
{
DataList = await Task.Run(() => GetData());
}
catch
{
// TODO: Log
}
}
private List<Data> GetData()
{
using (var context = new MyDataContext())
{
return context.Data.ToList();
}
}
/ try
;由于catch
被视为&#34;顶级&#34;异步操作。
答案 1 :(得分:0)
用这个代替代码:
public DetailViewModel(INavigationService navigationService)
{
Task.Run(() =>
{
GetData();
});
}
private void GetData()
{
using (var context = new MyDataContext())
{
var result = await (from data in context.Data
select data).ToListAsync();
DataList = new ObservableCollection<Data>(result);
}
}
答案 2 :(得分:-1)
这种方式可以按预期工作:
public DetailViewModel(INavigationService navigationService)
{
Task.Run(() =>
{
GetData();
}).ContinueWith(
(x) =>
{
Execute.OnUIThread(
() => DataList = new ObservableCollection<Data>(x.Result));
});
};
}
private Task<List<Data>> GetData()
{
using (var context = new MyDataContext())
{
return await (from data in context.Data
select data).ToListAsync();
}
}
感谢您的建议。