我试图在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 "";
}
但是当编译器达到 -
时var response = (HttpWebResponse) await request.GetResponseAsync();
它跳过剩下的代码,我从来没有得到响应。我知道代码是有效的 - 因为它在没有任务的情况下工作得很好,在异步void方法中。
任何人都知道如何解决这个问题,或者我做错了什么?我也在vs2015尝试了这个,但它也一样。
答案 0 :(得分:8)
你对UI线程有一个死锁。
当需要完成异步方法时,您将使用Task.Result
阻止线程,该异步方法将完成它正在等待的任务。
这就是为什么你不应该在异步代码上同步阻塞的原因。您应该等待从GetToken
返回的任务:
string token = await GetToken(serviceURI);
如果您无法在该方法中使用async,请将该逻辑移至其他方法(例如OnLoad
事件处理程序)。
另一种解决方案是在ConfigureAwait
任务上使用GetResponseAsync
,因此该方法的其余部分不会在UI线程上运行,从而避免死锁:
var response = (HttpWebResponse) await request.GetResponseAsync().ConfigureAwait(false);