嵌套异步并在表单中等待

时间:2015-03-18 23:13:07

标签: c# android xamarin xamarin.forms xamarin-studio

我在Mac Mini上使用Xamarin Forms和Xamarin Studio,我有一个异步/等待问题,我希望有人可以提供帮助。我有一个按钮点击事件定义为:

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

然后调用一个方法进行一些用户配置文件初始化,它需要联系服务器:

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

无论ConfigureAwait是否存在,这都会无限期等待。用户配置文件服务简单地执行以下操作(只返回自己进行测试):

    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 (..);
    }

ConfigureAwait(false)Task.Delay窒息。没有它,它可以工作,但调试器崩溃了。发生了什么,如何解决这个问题,以便AJAX请求(当我将来在用户配置文件服务中替换它)时会有效?

1 个答案:

答案 0 :(得分:2)

Sync-over-async是一个反模式;你不仅要接受自己的代码(必须在任何地方使用ConfigureAwait(false)),而且还要受你所调用的任何库的支配。特别是,我过去在Xamarin上遇到过关于Task.Delay的类似问题。在尝试将其切换为真正的网络呼叫之前,HttpClient在某些移动平台(iOS或Android,不记得ATM)上存在同样的问题。不确定Facebook是否会有类似的错误。

因此,总而言之,你真的不能那样做。相反,一直拥抱async

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

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

如果必须,请禁用控件,但不要阻止。这种方法的一个很好的副作用是你的应用程序总是更具响应性。