【问题标题】:Load large sets of data in ViewModel without blocking UI在 ViewModel 中加载大量数据而不阻塞 UI
【发布时间】:2015-05-02 05:11:50
【问题描述】:

我想在页面加载后加载我的视图模型,但我似乎不知道如何执行此操作。

这是 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;
    }
}

【问题讨论】:

  • 不应该是-await viewModel.LoadViewModel();防止阻塞?
  • 但这不会使 NavigationHelper_LoadState() 方法暂停(等待)直到它完成。基本上阻止页面被加载?我想加载页面 UI,然后让 ViewModel 加载它的数据。

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


【解决方案1】:

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

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

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

【讨论】:

  • 我试过了,但没用。我相信我正在正确地实现其他异步类,因为我在运行异步代码的任何地方都放置了等待语句。我用更多代码更新了我的问题。
  • 这很奇怪。不知道为什么要花很长时间。尝试从处理中删除代码,直到它再次开始快速工作,这将表明存在问题的代码。
  • 在我的其他代码中,我正在等待来自 Azure 移动服务的 MobileServiceSyncTable 的 PullAsync(),它具有预期的效果。基本上,UI 线程在等待 Pull 方法运行时不会被阻塞。但是在这里,它会被阻塞,直到它运行完所有代码。代码在同一个类中会导致这个问题吗?它在哪里调用外部方法?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-03-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-04-24
相关资源
最近更新 更多