【问题标题】:Issue with async Task<T> in xamarin formsxamarin 表单中的 async Task<T> 问题
【发布时间】:2015-08-12 16:26:17
【问题描述】:

我正在尝试在 Visual Studio 2013 上的 xamarin 共享项目中使用带有 REST 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();

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

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

【问题讨论】:

  • 提示:我会考虑使用HttpClient 而不是HttpWebRequest - 这是一个更高级别的抽象,它通常避免处理流。
  • 我喜欢,但是我编写的代码应该由另一个开发人员翻译成 java - 而且我不应该使用不能在 java 中使用的代码 - 或者至少很容易翻译。

标签: c# asynchronous xamarin async-await task


【解决方案1】:

您的 UI 线程出现了死锁。

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

这就是为什么您不应该在异步代码上同步阻塞。您应该等待从GetToken 返回的任务:

string token = await GetToken(serviceURI);

如果您不能在该方法中使用异步,请将该逻辑移至其他方法(例如 OnLoad 事件处理程序)。

另一种解决方案是在 GetResponseAsync 任务上使用 ConfigureAwait,这样该方法的其余部分就不会在 UI 线程上运行,从而避免死锁:

var response = (HttpWebResponse) await request.GetResponseAsync().ConfigureAwait(false);

【讨论】:

猜你喜欢
  • 1970-01-01
  • 2020-11-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-08-01
  • 2013-11-08
  • 1970-01-01
  • 2021-10-26
相关资源
最近更新 更多