HttpRequestException при выполнении client.SendAsync

Внезапно этот фрагмент кода, который обычно работает, начал выдавать ошибки HttpRequestException. В логах я вижу, что запрос действительно был отправлен за 1 минуту и ​​35 секунд до появления ошибки. Может дело в тайм-ауте?

Вот код:

private async Task<HttpResponseMessage> RunRequest(HttpRequestMessage request)
{            
    var client = new HttpClient();
    var response = await client.SendAsync(request).ConfigureAwait(false);              
    return response;           
}

Вот вызывающий абонент (может быть от 10 до 50 тысяч элементов):

int counter = 0;
var tasks = items.Select(async i =>
{
    if (await RunRequest(CreateRequest(i)))
        counter++
}).ToList();

if (tasks.Any())
{ 
    await Task.WhenAll(tasks);
}

Вот ошибка:

System.Net.Http.HttpRequestException: An error occurred while sending the request. ---> System.Net.WebException: The request was aborted: The request was canceled.
        at System.Net.HttpWebRequest.EndGetResponse(IAsyncResult asyncResult)
        at System.Net.Http.HttpClientHandler.GetResponseCallback(IAsyncResult ar)
        --- End of inner exception stack trace ---
        at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
        at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
        at MyClass.<RunRequest>d__c.MoveNext()
        --- End of inner exception stack trace ---
        at MyClass.<RunRequest>d__c.MoveNext()
        --- End of stack trace from previous location where exception was thrown ---
        at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
        at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
        at MyClass.<RunRequest>d__0.MoveNext()

Есть ли ограничение, с которым может справиться Task.WhenAll?


person Prabhu    schedule 08.08.2014    source источник
comment
Внезапно... Итак, что изменилось?   -  person Stephen Cleary    schedule 09.08.2014
comment
Ничего, что я могу придумать. На самом деле этот код работает хорошо большую часть времени. Эта ошибка возникает случайно. Единственным возможным изменением/переменной может быть количество выполняемых запросов. Вызовов RunRequest могло быть около 10000.   -  person Prabhu    schedule 09.08.2014
comment
Сколько времени обычно занимает каждый запрос?   -  person Yuval Itzchakov    schedule 09.08.2014
comment
Обычно всего несколько секунд, но в этом случае я заметил, что ошибка появилась через 2 минуты. Есть ли максимальное количество запросов, которые можно сделать за раз? У меня есть механизм регулирования, который разрешает только определенное количество запросов в данный момент времени, но я не могу контролировать, сколько ответов возвращается одновременно, так что может быть проблема в этом?   -  person Prabhu    schedule 09.08.2014
comment
Ограничивает ли ваш сервер количество запросов, которые могут обрабатываться одновременно?   -  person Yuval Itzchakov    schedule 09.08.2014
comment
Вы где-то вызываете ожидание или результат какой-то задачи? Это может быть ложный тупик, приводящий к тайм-ауту.   -  person usr    schedule 09.08.2014
comment
@usr У меня нет ожидания, но я обновил свой пост кодом вызова, возможно, это прольет свет? Когда эта ошибка была выброшена, было 10K+ элементов, так что много задач.   -  person Prabhu    schedule 09.08.2014
comment
@YuvalItzchakov Я так не думаю, но мне придется перепроверить.   -  person Prabhu    schedule 09.08.2014
comment
ошибка появилась через 2 минуты: вы уверены, что на самом деле это не 1 минута 40 секунд? таймаут по умолчанию 100 секунд   -  person Thomas Levesque    schedule 09.08.2014
comment
@ThomasLevesque, на самом деле, вы правы, это была ровно 1 минута 35 секунд.   -  person Prabhu    schedule 09.08.2014
comment
10000 — это много запросов, которые нужно отправить на сервер одновременно. Возможно, вы захотите немного их пошатнуть. Нет ограничений на WhenAll; это почти наверняка проблема масштабируемости сервера (не в вашем коде). То есть, если сервер не async, он не может так быстро реагировать на внезапные изменения объема запросов.   -  person Stephen Cleary    schedule 10.08.2014


Ответы (1)


Если все ваши запросы относятся к одному и тому же домену, вам нужно добавить это в свой файл «Web.config» (по умолчанию всего 2):

<configuration>
    <system.net>
        <connectionManagement>
            <add address="*" maxconnection="100" />
        </connectionManagement>
    <system.net>
<configuration>

И вы уже ожидаете каждого отдельного RunRequest по очереди, последовательно, поэтому на самом деле ничего не запускается параллельно - и ваш Task.WhenAll должен вызывать исключение, поскольку вы даете ему список HttpResponseMessage вместо списка Task.

RunRequest не возвращает bool, так как вы используете его в if?

...в этом коде так много неправильного...

person Nikola Bogdanović    schedule 09.03.2015
comment
@Prabhu - тогда вы не ждете RunRequest, что хорошо, но опубликованный вами псевдокод даже не скомпилируется, не говоря уже о запуске ... опубликуйте настоящий - person Nikola Bogdanović; 10.03.2015