Async await and OnNavigatedTo #wpdev

Update: this only applies to #wpdev and using async CTP for async task mechanism. I have had a lot of feedback and after a bit of rework, i can do it right in #win8dev. see this post https://invokeit.wordpress.com/2012/10/24/async-task-mechanism-and-onnavigatedto-part-2-win8dev/

I am sure i am not the only one with bad coding habits. Maybe its just me or maybe i am more common than i’d like to think but here’s how i deal with loading data i require per page.

When a XAML page is called, i tend to override OnNavigatedTo event. This is where i put all the calls to load / fire data. If i am going to make web service calls or read from storage, it tends to happen in OnNavigatedTo method.

Over the last few months, i have migrated 2 of my apps from Windows Phone to Windows 8 and for the 3rd, i have taken a slightly different approach. Instead of jumping straight and porting it, i put the app in #WPDev under scissors and i am making code easily shareable between the two.

Step 1: Install Async CTP for VS 2010 (make sure you pray to whatever thing you believe in).. if that doesn’t work.. try threatening whatever thing you believe in.. if you are lucky Async CTP might just install 🙂

Step 2: Convert event driven async code to async await type code. For WebClient i found a helper class, you can download it here http://softwareblog.alcedo.com/post/2012/01/25/TaskCompletionSource-in-real-life-(part-2-of-2).aspx. It exposes awaitable Web Client and I used that to convert all other Event drive code to Task driven code

Here’s where the problem started. I tend to fire off the async event driven calls in OnNavigatedTo
If i change it to async await.. it doesn’t really work (at least not how i want it to). I have noticed the same with async await on Windows 8.

AsyncDataSourceObj aeo = new AsyncDataSourceObj();
protected override void OnNavigatedTo(NavigationEventArgs e)
{
    aeo.UseEventStyleCallCompleted += OnUseEventStyleCallCompleted;
    aeo.UseEventStyleCall();
}

private void OnUseEventStyleCallCompleted( /* args */ )
{
    // show the data
    // make sure you use Dispatcher when touching UI objects
}

Now suppose we modified the above code to use async await

AsyncDataSourceObj aeo = new AsyncDataSourceObj();
protected async override void OnNavigatedTo(NavigationEventArgs e)
{
    MyDataType mydata = await aeo.UseAsyncAwaitStyleCall();

    // now show the data.
}

This doesn’t seem to work correctly… maybe because i am declaring OnNavigatedTo async or maybe because i am making it pause and continue in a fashion it wasn’t supposed to… well i got tired eventually and this is what i settled for something that looks like this

AsyncDataSourceObj aeo = new AsyncDataSourceObj();
protected override void OnNavigatedTo(NavigationEventArgs e)
{
    ThreadPool.QueueUserWorkItem(new WaitCallback(f =>
    {
        Task<MyDataType> tmydata = aeo.UseAsyncAwaitStyleCall();
        tmydata.Wait();

        // now show the data.
        // use dispatcher to manipulate UI controls
    }));
}

this is a compromise between a purist Async Await usage and actually doing things the way i like it. And just FYI, it works beautifully

I haven’t done any hacks.. these methods are exposed.. i have just spawned off the async wait on a Threadpool thread myself.. sure the system could have done it but someone it didn’t like the way i did it. Oh well

Advertisement

9 thoughts on “Async await and OnNavigatedTo #wpdev

  1. An alternative solution is to put your async function in a separate async method. You can then call that function from your OnNavigated to.
    The reason it will cause you issue there is that you are holding up the loading process of the page which should never be done (unless you really cannot help it), you shouldn’t try to add async any of the core override functions.

    As a sidenote, if you are loading data to be presented into a page you should really be using MVVM or other framework and loading the data asynchronously there while showing some kind of “Waiting” information to the user until it’s ready, that way the page completely loads and updates when data has been returned.

    • Being a coder like I am.. I still haven’t gotten up to speed with MVVM 🙂 You will agree what I have done is effectively inline async method call by directly using ThreadPool

  2. Wierd. This should theoritically work.
    Why did you write this:
    Task mydata = await aeo.UseAsyncAwaitStyleCall();
    instead of this :
    ReturnType mydata = await aeo.UseAsyncAwaitStyleCall();
    ?
    Is your async method returning a Task ? There
    might be a problem with how you use async that makes this not work.
    Can you post the code of the UseAsyncAwaitStyleCall as well?

    • Also note that making the OnNavigatedTo method an async DOES NOT mean that it takes as much time to complete
      as the whole async workflow. OnNavigatedTo is fire and forget by the superclass and returns immediately after
      the first async call.So there should be no issue with the method taking too much time and therefore having your app
      being killed by the OS.

      • Here’s my 2p on it.. OnNavigatedTo is fired when navigation starts. await actually suspends execution and waits for the web service call. and then continues execution. that is the problem.. syntacically its all fine..

      • “await actually suspends execution” . In a correct async scenario execution is indeed suspended similarly to how iterators work (state machine) but control is returned to the calling thread which means it does not block. It seems in your case that your UIThread is blocked so i am leaning towards the explanation that the implementation of the task you are awaiting is actually run synchronously on the calling thread. That would explain it i think. Async has pitfalls…

  3. Pingback: Async await and OnNavigatedTo #wpdev #win8dev

  4. Pingback: Async Task mechanism and OnNavigatedTo Part 2 #win8dev | Invoke IT Limited

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s