HttpClient请求在asp .net Project中不起作用

时间:2017-01-27 16:47:31

标签: asp.net-mvc api request console-application dotnet-httpclient

我正在使用HttpClient向api发出请求。此代码位于与两个附加项目共享的类库项目中,即Console和Asp.Net Mvc项目。当我从Console项目发出请求时它工作得很好,但是在asp项目中它阻塞了行

using(Stream responseStream = await response.Content.ReadAsStreamAsync()

这是我的请求代码

private async Task<dynamic> ReadJson(string url)
        {
            HttpResponseMessage response = await httpClient.GetAsync(url);

            if (response.StatusCode == System.Net.HttpStatusCode.NoContent)
                throw new RateLimitException();

            if (response.StatusCode == System.Net.HttpStatusCode.Forbidden)
                throw new AccessDeniedException();

            if (response.StatusCode != System.Net.HttpStatusCode.OK)
                throw new Exception("Error: " + response.StatusCode);

            using (Stream responseStream = await response.Content.ReadAsStreamAsync())
            using (StreamReader sr = new StreamReader(responseStream, System.Text.Encoding.UTF8))
            {
                string json = sr.ReadToEnd();
                return JObject.Parse(json);
            }
        }

我正在从Console和Asp.Net项目调用该方法。从控制台工作,但读取响应内容时,asp .net项目在行中阻塞

1 个答案:

答案 0 :(得分:4)

最有可能发生这种死锁,因为调用ReadJson函数的控制器操作是同步的。您需要使操作异步。你可以找到这个死锁here的一个很好的解释。 (所有学分都归Stephen Cleary所有)

快速摘要是:

/ My "library" method.
public static async Task<JObject> GetJsonAsync(Uri uri)
{
  using (var client = new HttpClient())
  {
    var jsonString = await client.GetStringAsync(uri);
    return JObject.Parse(jsonString);
  }
}

// My "top-level" method.
public class MyController : ApiController
{
  public string Get()
  {
    var jsonTask = GetJsonAsync(...);
    return jsonTask.Result.ToString();
  }
}
     

导致死锁的原因

     
      
  1. 顶级方法调用GetJsonAsync(在UI / ASP.NET上下文中)。 GetJsonAsync通过调用启动REST请求   HttpClient.GetStringAsync(仍在上下文中)。

  2.   
  3. GetStringAsync返回未完成的任务,表示REST请求未完成。

  4.   
  5. GetJsonAsync等待GetStringAsync返回的任务。捕获上下文并将用于继续运行   GetJsonAsync方法稍后。 GetJsonAsync返回未完成的   任务,表示GetJsonAsync方法未完成。
  6.   
  7. 顶级方法同步阻止GetJsonAsync返回的任务。这会阻止上下文线程。
  8.   
  9. ...最终,REST请求将完成。这样就完成了GetStringAsync返回的任务。
  10.   
  11. GetJsonAsync的延续现在已准备好运行,它等待上下文可用,以便它可以在上下文中执行。
  12.   
  13. 死锁。顶级方法是阻塞上下文线程,等待GetJsonAsync完成,GetJsonAsync正在等待   上下文是免费的,所以它可以完成。
  14.         

    防止死锁

         

    有两种最佳做法可以避免这种情况:

         
        
    1. 在“库”异步方法中,尽可能使用ConfigureAwait(false)。
    2.   
    3. 不要阻止任务;一直使用async。
    4.