简体   繁体   中英

Nested Async and Await in Forms

I'm using Xamarin Forms with Xamarin Studio on a Mac Mini, and I'm having an async/await issue I was hoping someone could help with. I have a button click event defined as:

void LoginButton_Clicked (object sender, EventArgs e)
{
  //Do some stuff
  this.HandleSignInCompleted(..);
}

This then calls a method to do some user profile initialization, which it needs to contact the server:

async void HandleSignInCompleted(..)
{
  var profile = await _profileService.GetAsync ().ConfigureAwait(false);

This waits indefinitely, whether ConfigureAwait is present or not. The user profile service simple does the following right now (just returns myself for testing):

    public async Task<UserProfile> GetAsync()
    {
        //wrapper around app properties
        var accessToken = (string)_appProperties.Get ("token"); 

        //Tried with ConfigureAwait and without
        await Task.Delay (100);

        //TODO:replace with facebook load
        return new UserProfile (..);
    }

With ConfigureAwait(false) , Task.Delay chokes. Without it, it works, but the debugger crashed. What's going on and how can I resolve this issue so that the AJAX request (when I replace it in the user profile service in the future) will work?

Sync-over-async is an antipattern; you're at the mercy not only of your own code (must use ConfigureAwait(false) everywhere), but also at the mercy of any libraries you call. In particular, I've run into a similar issue on Xamarin in the past regarding Task.Delay . And before you try switching it out for a real network call, HttpClient has the same problem on some mobile platforms (either iOS or Android, don't remember ATM). Not sure if Facebook would have a similar bug or not.

So, in summary, you really just can't do that. Instead, embrace async all the way:

async Task HandleSignInCompletedAsync(..)
{
  var profile = await _profileService.GetAsync ().ConfigureAwait(false);
}

async void LoginButton_Clicked (object sender, EventArgs e)
{
  //Do some stuff
  await this.HandleSignInCompletedAsync(..);
}

Disable controls if you have to, but don't block. A nice side effect of this approach is that your app is always more responsive.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM