Вызов HttpClient и получение идентичных результатов от постраничных запросов - это я или служба? - PullRequest
0 голосов
/ 06 ноября 2019

Я отправляю пять запросов HttpClient на один и тот же URL-адрес, но с другим параметром номера страницы. Все они запускают асинхронно, и затем я жду, когда они завершат использование Tasks.WaitAll (). Мои запросы используют System.Net.Http.HttpClient.

Это в основном работает нормально, и я получаю пять разных результатов, представляющих каждую страницу данных примерно в 99% случаев.

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

Я звоню в стороннюю веб-службу, над которой у меня нет контроля. Поэтому, прежде чем слишком надрывать свою команду по этому поводу, я хочу знать, могу ли я что-то здесь делать неправильно или есть какой-то аспект HttpClient ot Task, который я пропускаю.

Вот вызовcode:

    for (int i = 1; i <= 5; i++)
    {
        page = load_made + i;
        var t_page = page;
        var t_url = url;
        var task = new Task<List<T>>(() => DoPagedLoad<T>(t_page, per_page, t_url));
        task.Run();
        tasks.Add(task);
      }
      Task.WaitAll(tasks.ToArray());

Вот код в DoPagedLoad, который возвращает задачу:

 var client = new HttpClient();
 var response = client.GetAsync(url).Result;
 var results = response.Content.ReadAsStringAsync().Result();

Я был бы признателен за любую помощь от людей, знакомых с возможными причудами Task и HttpClient

ПРИМЕЧАНИЕ. Run - это метод расширения, помогающий с асинхронными исключениями.

        public static Task Run(this Task task)
        {
            task.Start();
            task.ContinueWith(t => 
            {
                if(t.Exception != null)
                    Log.Error(t.Exception.Flatten().ToString());
            });
            return task;
        }

1 Ответ

1 голос
/ 06 ноября 2019

Трудно дать однозначный ответ, потому что у нас нет всех деталей, но вот пример реализации того, как вы должны запускать HTTP-запросы. Обратите внимание, что ожидаются все асинхронные операции - Result и Wait / WaitAll не используются. Вы почти никогда не должны / не должны использовать какие-либо из них - они блокируются синхронно и могут создавать проблемы.

Также обратите внимание, что для HTTP-клиента не определены глобальные контейнеры cookie, заголовки по умолчанию и т. Д. Если вам нужно что-то из этого, просто создайте отдельные объекты HttpRequestMessage и добавьте все заголовки, которые вам нужно добавить. Не используйте глобальные свойства - гораздо проще просто установить свойства для каждого запроса.

// Globally defined HTTP client.
private static readonly HttpClient _httpClient = new HttpClient();

// Other stuff here...

private async Task SomeFunctionToGetContent()
{
    var requestTasks = new List<Task<HttpResponseMessage>>();
    var responseTasks = new List<Task>();

    for (var i = 0; i < 5; i++)
    {
        // Fake URI but still based on the counter (or other
        // variable, similar to page in the question)
        var uri = new Uri($"https://.../{i}.html");

        requestTasks.Add(_httpClient.GetAsync(uri));
    }

    await (Task.WhenAll(requestTasks));

    for (var i = 0; i < 5; i++)
    {
        var response = await (requestTasks[i]);

        responseTasks.Add(HandleResponse(response));
    }

    await (Tasks.WhenAll(responseTasks));
}

private async Task HandleResponse(HttpResponseMessage response)
{
    try
    {
        if (response.Content != null)
        {
            var content = await (response.Content.ReadAsStringAsync());

            // do something with content here; check IsSuccessStatusCode to
            // see if the request failed or succeeded
        }
        else
        {
            // Do something when no content
        }
    }
    finally
    {
        response.Dispose();
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...