locked
Call to async method from within LoadState blocks UI RRS feed

  • Question

  • I'm trying to navigate to a second page from my Windows Store app, but when I do so the UI is blocked until the data for the second page is loaded and bound to the controls on the page.  In other words, the first page hangs until data is loaded and bound prior to showing the second page.  What I want instead is to have the second page displayed immediately so that I can put a progressbar there to indicate data is being fetched.

    In PageOne, an app bar button's event handler contains the following:

    this.Frame.Navigate(typeof(PageTwo));

    In the LoadState event on PageTwo, I instantiate my ViewModel and set the page's DataContext to that ViewModel.  Here's where the problem occurs:  the ViewModel has an async method that is responsible for loading the data.  Even though I try to call that method asynchronously, it always blocks the second page from being displayed for close to 2 seconds until the ViewModel retrieves its data.

    I've tried using the new Async & Await functionality as well as using callbacks and no matter what I do the UI is blocked until data is being fetched and bound to the controls.  Here are some examples of what I've done in PageTwo:

    MyViewModel vm = null;
    protected override void LoadState(...)
    {
    vm = new MyViewModel();
    this.DataContext = vm;
    Window.Current.Activate();

    GetViewModelDataAsync();
    }

    private async void GetViewModelDataAsync()
    {
    await vm.InitAsync();
    }

    I've tried other variations as well.  I've tried the following inside the LoadState event:

    this.DataContext = await vm.InitAsync();  //where InitAsync returns the proper type for the data context

    I've tried using Task.Run:

    var t = Task.Run(async () => { await vm.InitAsync(); });

    The only thing I've been able to do to get around this issue is the following, which is quite messy.  This actually allows the second page to load immediately.

    In LoadState:

    timer.Start()

    And in in PageTwo's constructor, I have the following:

    timer.Tick += (o, e) =>
    {
    timer.Stop();
    this.DataContext = await vm.InitAsync();
    };

    Any thoughts?  Thanks.

    Tuesday, October 16, 2012 1:45 PM

Answers

  • skydrive link? or email it at dave[at]familie-smits.com
    • Proposed as answer by Dave SmitsMVP Tuesday, December 4, 2012 12:40 PM
    • Marked as answer by Tim SF Tuesday, December 4, 2012 2:52 PM
    Tuesday, October 16, 2012 2:04 PM

All replies

  • well ofcourse the data have still to be fetched and wont show before its there. but the idea about async its keeps responding. simple test: add a progress indictor, show it before you load async the data and hide when the data is loaded (after the await)
    Tuesday, October 16, 2012 1:49 PM
  • That's the problem...PageTwo doesn't even get displayed for me to show a progress indicator.  In other words, when I click the button on PageOne to navigate to PageTwo, PageOne stays frozen for close to 2 seconds before the app finally navigates to PageTwo.

    What I want to happen is for PageTwo to be displayed immediately so that I can display a progress indicator there.  Does that make sense?

    Tuesday, October 16, 2012 1:52 PM
  • got some minimal code (in a project that you can share) so we can have a look?
    Tuesday, October 16, 2012 1:56 PM
  • It will take me a little bit to strip out everything that isn't relevant.  How should send it to you?
    Tuesday, October 16, 2012 1:59 PM
  • skydrive link? or email it at dave[at]familie-smits.com
    • Proposed as answer by Dave SmitsMVP Tuesday, December 4, 2012 12:40 PM
    • Marked as answer by Tim SF Tuesday, December 4, 2012 2:52 PM
    Tuesday, October 16, 2012 2:04 PM