0

Я использую HttpClient для запроса на api. Этот код находится в проекте библиотеки классов, совместно используемом двумя дополнительными проектами, Консоль и проект Asp.Net Mvc. Когда я делаю запрос от проекта консольного он прекрасно работает, но в нем блоках жереха проекта в строкеЗапрос HttpClient не работает в asp .net Project

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

Я делаю тот же призыв к метод из Консоли и проекта Asp.Net. От консоли работает, но проект asp .net блокируется в строке при чтении содержимого ответа

+0

Попробуйте вызвать методы асинхронных синхронно, как это: 'httpClient.Get (URL) и' response.Content.ReadAsStream() 'и скажите мне, если до сих пор блоков. – Alisson

+1

Вам нужно сделать действие в MVC-контроллере 'async', а также –

+0

@Alisson httpClient не имеет метода Get() и Content, не имеет ReadAsStream(). Im Я пропустил некоторое пространство имен? –

ответ

3

Скорее всего, этот тупик происходит потому, что действие контроллера, вызывающее функцию ReadJson, является синхронным. Вам нужно сделать асинхронное действие. Вы можете найти отличное объяснение этого тупика here. (Все кредиты идут Стивен Клири)

Краткое резюме является:

/ 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 (в пользовательском интерфейсе /ASP.NET). GetJsonAsync запускает запрос REST, вызывая HttpClient.GetStringAsync (все еще в контексте).

  2. GetStringAsync возвращает незавершенную задачу, указывая, что запрос REST не завершен.

  3. GetJsonAsync ожидает задачу, возвращенную GetStringAsync. Контекст захвачен и будет использоваться для продолжения использования метода GetJsonAsync . GetJsonAsync возвращает незавершенную задачу , указывая, что метод GetJsonAsync не завершен.
  4. Метод верхнего уровня синхронно блокирует задачу, возвращенную GetJsonAsync. Это блокирует контекстный поток.
  5. ... В конце концов, запрос REST будет завершен. Это завершает задачу, которая была возвращена GetStringAsync.
  6. Продолжение для GetJsonAsync теперь готово к запуску и ожидает, что контекст будет доступен, чтобы он мог выполняться в контексте.
  7. Тупик. Метод верхнего уровня блокирует поток контекста, ожидая завершения GetJsonAsync, и GetJsonAsync ждет контекста, который будет бесплатным, чтобы он мог завершить.

Предотвращение Тупик

Есть две лучшие практики, избежать этой ситуации:

  1. В вашей «библиотеки» асинхронными методами, используйте ConfigureAwait (ложь), где это возможно.
  2. Не блокируйте задачи; используйте async полностью вниз.
+0

Мой контроллер не async, но я вызываю метод wait из задачи, возвращаемой методом ReadJson. Как сказал @Alisson, это хорошая практика, но это не должно быть причиной моей проблемы. Я все равно подпишу. –

+0

«Мой контроллер не асинхронный, но я вызываю метод wait ...» Именно в этом и есть проблема. Не делайте этого - это вызывает взаимоблокировки. Сделайте свой асинхронный контроллер. –