与异步数据加载和backgroundWorker的数据绑定

时间:2014-01-16 12:50:07

标签: c# asynchronous windows-phone-8 backgroundworker azure-mobile-services

我非常感谢有关如何正确执行此操作的反馈。

我在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事件并仅下载用户当前正在查看的数据。这是正确的方法吗?

1 个答案:

答案 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();
}