在ViewModel中加载大量数据而不阻止UI

时间:2015-03-01 22:16:44

标签: c# mvvm windows-store-apps windows-phone-8.1 mvvm-light

我希望在页面加载后加载我的viewmodel,但我似乎无法弄清楚如何执行此操作。

这里是viewModel方法,其中LoadViewModel内的两个方法都是长时间运行异步方法:

public async Task LoadViewModel()        
{
    await GetAllTiles();
    await UpdateAllScenarioCardsAsync(); 
}

在视图中,我尝试这样的事情:

private async void NavigationHelper_LoadState(object sender, LoadStateEventArgs e)
{
    var viewModel = DataContext as StatsViewModel;
    if (viewModel != null)
    {
        var statsViewModel = viewModel;
        await statsViewModel.LoadViewModel();
    }
}

由于某种原因,即使我删除了GetAllTiles()和UpdateAllScenarioCardsAsync()的等待,LoadViewModel()方法也会阻止整个UI ...在页面加载之前运行NavigationHelper_LoadState方法,所以我尝试注册LoadViewModel()到页面的Loaded事件,但我似乎无法使它工作。

修改 这是我的UpdateAllScenarioCardsAsync()类。 UpdateTotalTilesAsync()和UpdataTodayTilesAsync()在代码中也有await语句,但它仍然阻止了UI。我使用了closedScenario,因为我认为这个问题可能是在一个错误的范围内关闭一个变量,就像在question中回答的那样,但现在仍然运气好。我很想认为它与foreach循环有关,因为我已经在我的解决方案中成功地完成了这个并且它没有阻止UI线程,但是该代码没有foreach循环。

private async Task UpdateAllScenarioCardsAsync()
{
    IsPending = true;

    try
    {
        // Load all of the scenario cards
        foreach (var scenario in _scenariosList)
        {
            var closedScenario = scenario;
            var data = new ScenarioDataCard(closedScenario);
            await UpdateTotalTiles(data);
            await UpdateTodayTestedTiles(data);
            ScenarioDataCards.Add(data);
        }
    }
    catch (Exception ex)
    {
        Debug.WriteLine(ex.Message);
    }
    finally
    {
        IsPending = false;
    }
}

1 个答案:

答案 0 :(得分:0)

您需要在LoadState事件处理程序中添加await。否则它将在等待LoadViewModel()返回时简单地阻塞。像这样......

private async void NavigationHelper_LoadState(object sender, LoadStateEventArgs e)
{
    var viewModel = DataContext as StatsViewModel;
    if (viewModel != null)
    {
        await viewModel.LoadViewModel();
    }
} 

我还假设实现了 GetAllTiles UpdateAllScenarioCardsAsync 方法,以便它们确实可以在另一个线程上执行工作,这样它们就不会阻塞主用户界面线程。