Unable to read data from the transport connection System.IO.IOException

Есть задача - асинхронно распарсить данные, get запросов очень много, поэтому решил распараллелить вот таким образом.

await Task.Run(() =>
{
    Parallel.ForEach(collection, (itemFrom) =>
    {
        foreach (var itemTo in collection)
        {
            List<ResponseModel> result = default;
            try
            {
                result = (List<ResponseModel>)ParseByCurrencyAsync(itemFrom.Key, itemTo.Key).Result;
            }
            catch (Exception ex){ }
        }
    });
});

В результате получаю ошибку из заголовка темы, ну и вот это дело code

Почитал информацию по данной ошибке, судя по всему истекает время ожидания ответа. Видимо очень много запросов и сервер их блокирует. Подскажите пожалуйста, есть ли какое то решение для данной задачи?


Ответы (1 шт):

Автор решения: aepot

Исключение возвращает метод ParseByCurrencyAsync, и показанный код здесь не при чем. Но это плохой код, технически и семантически. Вот хороший эквивалент:

var tasks = new List<Task<List<ResponseModel>>>();
foreach (var itemTo in collection)
{
    tasks.Add(ParseByCurrencyAsync(itemFrom.Key, itemTo.Key));
}
List<ResponseModel>[] result = await Task.WhenAll(tasks);

Но я на вашем месте бы задумался над ограничением количества одновременно работающих запросов


Никогда не используйте .Result, его можно использовать только для завершенных задач, например пусть будет некий task типа Task<int>:

// ВОТ ТАК НЕЛЬЗЯ
int number = task.Result;

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

Другой пример

// вот так можно
await task;
int number = task.Result;

А проще

int number = await task;

Как видите, практической пользы от .Result никакой, но она иногда есть, вот рабочий пример, где я не знаю, синхронно завершился вызванный метод или асинхронно (да, такое тоже бывает):

if (!task.IsCompleted)
{
    await task;
}
int number = task.Result;

Что-то вроде оптимизации, запускаю ожидание только если нужно. Но случай действительно редкий и большинство разработчиков, чтобы не путатья сделают проще int number = await task;, и я вам тоже советую использовать только await, и никак иначе.

→ Ссылка