xamarin表单中的异步任务<T>问题

One*_*ion 2 c# asynchronous task async-await xamarin

我正在尝试在Visual Studio 2013上的xamarin共享项目中使用Azure api的Azure媒体服务.这是我用来获取访问令牌的代码.

public HttpFactory()
{
    string token = GetToken(serviceURI).Result;
    //some more methods also async tasks
}

private async Task<string> GetToken(Uri serviceUri)
{
    HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(serviceURI);
    request.Accept = "application/json";
    request.Method = "GET";
    request.Headers["Host"] = "media.windows.net";
    request.Headers["x-ms-version"] = "2.9";
    request.Headers["Authorization"] = "Bearer " + token;
    var response = (HttpWebResponse) await request.GetResponseAsync();

    if (response.StatusCode == HttpStatusCode.MovedPermanently)
    {
        serviceURI = new Uri(response.Headers["Location"]);
        HttpWebRequest req = ( HttpWebRequest)WebRequest.Create(serviceURI);
        var res = (HttpWebResponse)await req.GetResponseAsync();

        using (Stream responseStream = res.GetResponseStream())
        {
            using (StreamReader reader = new StreamReader(responseStream))
            {
                string str = reader.ReadToEnd();
                // var test = JsonConvert.DeserializeObject(str);
                JToken jtoken = JsonConvert.DeserializeObject<JToken>(str);
                 return jtoken["access_token"].Value<string>();

            }
        }
    }
    return "";
}
Run Code Online (Sandbox Code Playgroud)

但是当编译器到达时 -

var response = (HttpWebResponse) await request.GetResponseAsync();
Run Code Online (Sandbox Code Playgroud)

它跳过其余的代码,我从来没有得到响应.我知道代码正在运行 - 因为它在没有任务的情况下工作得很好,在异步void方法中.

任何人都知道如何解决这个问题,或者我做错了什么?我也在vs2015尝试了这个,但它是一样的.

i3a*_*non 8

您在UI线程上遇到了死锁.

Task.Result需要在完成异步方法时阻塞线程,异步方法将完成它正在等待的任务.

这就是为什么你不应该同步阻塞异步代码.你应该等待从中返回的任务GetToken:

string token = await GetToken(serviceURI);
Run Code Online (Sandbox Code Playgroud)

如果您不能在该方法中使用async,请将该逻辑移动到其他方法(例如OnLoad事件处理程序).

另一种解决方案是ConfigureAwaitGetResponseAsync任务上使用,因此方法的其余部分不会在UI线程上运行,从而避免死锁:

var response = (HttpWebResponse) await request.GetResponseAsync().ConfigureAwait(false);
Run Code Online (Sandbox Code Playgroud)

  • 我还建议阅读Stephen Cleary的[不要阻止异步代码](http://blog.stephencleary.com/2012/07/dont-block-on-async-code.html) (2认同)