Ошибка при вызове HttpClient.GetAsync: базовое соединение было закрыто

У меня есть веб-сайт asp.net MVC, который потребляет остаток api для получения его данных. Я использую асинхронные задачи для выполнения запросов, поскольку на каждой странице может быть много. После некоторого времени безотказной работы веб-сайт бросает следующую ошибку при попытке получить данные.

Подключенное соединение было закрыто: при отправке произошла непредвиденная ошибка.

Я читал, что это может быть связано с настройками maxconnection на web.config, но увеличение этого, похоже, не имеет большого значения.

Я также использую кеширование, чтобы уменьшить нагрузку на api. Задача кэшируется, поэтому результат может быть использован позже.

Единственное, что я нашел, чтобы исправить это, - это перезапуск пула приложений. Любая помощь будет оценена.

/* Code from page_load */

var currenciesTask = ApiClient.GetAsync<CurrencyListWrapper>("currencies");
var blogArticleTask = ApiClient.GetAsync<BlogArticleListWrapper>("blog/articles", "limit=10");
var seoPageTask = ApiClient.GetAsync<SEOPageListWrapper>("seopages");

await Task.WhenAll(currenciesTask, blogArticleTask, seoPageTask);


/* Code from data access later */

public class ApiClient : HttpClient
{
  public static Task<T> GetAsync<T>(string operation, string query = null, bool cache = true)
  {
    // Check if task is in cache
    string cacheName = null;

    if (cache)
    {
      cacheName = String.Format("{0}_{1}_{2}", operation, query ?? String.Empty, App.GetLanguage());

      var cachedTask = HttpRuntime.Cache[cacheName];

      if (cachedTask != null)
      {
        return (Task<T>)cachedTask;
      }

    }

    // Get data task
    var task = GetAsyncData<T>(operation, query);

    // Add to cache if required
    if (task != null && cache)
    {
      App.AddToCache(cacheName, task);
    }

    return task;
  }

  public static async Task<T> GetAsyncData<T>(string operation, string query = null)
  {
    using (ApiClient client = new ApiClient())
    {
      string url;

      if (query != null)
      {
        url = String.Format("{0}?{1}", operation, query);
      }
      else
      {
        url = String.Format("{0}", operation);
      }

      var response = await client.GetAsync(url);

      return (await response.Content.ReadAsAsync<T>());
    }
  }
}

Ответ 1

Это неправильно,

Задача кэшируется, поэтому результат может быть использован позже.

Вы должны кэшировать результат, а не задачу. В конце первого выполнения ваш HttpClient закрывается, и когда вы пытаетесь получить кешированную задачу, это не сработает.

public class ApiClient : HttpClient
{
  public static async Task<T> GetAsync<T>(string operation, string query = null, bool cache = true)
  {
    // Check if task is in cache
    string cacheName = null;

    if (cache)
    {
      cacheName = String.Format("{0}_{1}_{2}", operation, query ?? String.Empty, App.GetLanguage());

      T cachedResult = (T)HttpRuntime.Cache[cacheName];

      if (cachedResult!= null)
      {
        return Task.FromResult(cachedResult);
      }

    }

    // Get data task
    var result = await GetAsyncData<T>(operation, query);

    // Add to cache if required
    if (result != null && cache)
    {
      App.AddToCache(cacheName, result);
    }

    return result;
  }

  public static async Task<T> GetAsyncData<T>(string operation, string query = null)
  {
    using (ApiClient client = new ApiClient())
    {
      string url;

      if (query != null)
      {
        url = String.Format("{0}?{1}", operation, query);
      }
      else
      {
        url = String.Format("{0}", operation);
      }

      var response = await client.GetAsync(url);

      return (await response.Content.ReadAsAsync<T>());
    }
  }
}

Ответ 2

Акаш может быть прав. Но проблема с подключением приложений кажется более или менее. Установите ограничение на соединение 0, чтобы сделать его неограниченным в пуле приложений. У вас наконец есть блок в коде, и

gc.collect();

метод сбора мусора, вызываемый для удаления неиспользуемых подключений, чтобы освободить место для другого соединения.