我非常感谢有关如何正确执行此操作的反馈。
我在WP8中有4个项目的全景视图。一个项目是map元素,rest 3显示从Azure移动服务下载的数据。在后面的主页面代码中,我设置了backgroundWorker和相关事件
private void bw_DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker worker = sender as BackgroundWorker;
App.ViewModel.LoadData();
System.Threading.Thread.Sleep(3000);
}
private void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
RefreshBinding();
}
在MainViewModel.cs中我有LoadData方法。
public async void LoadData()
{
PanItem1 = await PanItem1Table.ToCollectionAsync<PanItem1>();
PanItem2 = await PanItem2Table.ToCollectionAsync<PanItem2>();
PanItem3 = await PanItem3Table.ToCollectionAsync<PanItem3>();
}
RefreshBinding()只是相应地将3个panoramaItems的ItemSources设置为PanItem1-3。由于某种原因,在加载数据之前创建/绑定页面时绑定会无声地失败,之后必须重新设置ItemSource。
好的,这在纸面上看起来相当不错,但实际上我遇到了两个让我麻烦的细节。
1)bw_RunWorkerCompleted()立即被调用,它不等待异步操作完成(我认为它会)。我不得不在doWork()中添加人工睡眠(3000)。这远非最优,因为我无法确定数据是否在3s后填充。
有更好的方法吗?你能以某种方式验证异步操作的完成吗?
2)由于某种原因偶尔会失败,让应用程序完全空了。仅显示背景图像和标题,并且每个panoramaItem的所有内容都为空,并且地图无法完全加载。
我怀疑这是因为试图同时做太多事情。有没有一个简洁的解决方案如何平衡工作量?我最好的猜测是使用全景的SelectionChanged事件并仅下载用户当前正在查看的数据。这是正确的方法吗?
答案 0 :(得分:1)
首先,你错误地写了LoadData
,你应该这样写:
public async Task LoadDataAsync()
{
PanItem1 = await PanItem1Table.ToCollectionAsync<PanItem1>();
PanItem2 = await PanItem2Table.ToCollectionAsync<PanItem2>();
PanItem3 = await PanItem3Table.ToCollectionAsync<PanItem3>();
}
现在重写调用函数:
private void bw_DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker worker = sender as BackgroundWorker;
App.ViewModel.LoadData().Wait();
System.Threading.Thread.Sleep(3000);
}
这样您实际上将等待异步操作完成。但这仍然是错误的,你应该放弃整个BackgroundWorker
并只使用异步操作:
public async Task LoadDataAsync()
{
PanItem1 = await PanItem1Table.ToCollectionAsync<PanItem1>();
PanItem2 = await PanItem2Table.ToCollectionAsync<PanItem2>();
PanItem3 = await PanItem3Table.ToCollectionAsync<PanItem3>();
RefreshBinding();
}