Как параллельно обрабатывать несколько асинхронных задач цикла foreach

Как я могу одновременно обрабатывать несколько задач в каждом цикле forach, isconnected устанавливается вызовом await item.GetIsConnected(). На данный момент обновление идет медленно, поэтому я хотел бы, чтобы они обрабатывались одновременно.

До:

private async void Refresh()
{
    foreach (var item in Cars.ToList<Carnet>())
    {
        await item.GetIsConnected();
        if (item.IsConnected)
        {
            await item.GetCarDetailsAsync();
        }
    }
}

После:

private async void Refresh()
{
    List<Task> listOfTasks = new List<Task>();
    foreach (var item in Cars.ToList<Carnet>())
    {
        listOfTasks.Add(item.GetIsConnected());
        if (item.IsConnected)
        {
            await item.GetCarDetailsAsync();
        }
    }
    await Task.WhenAll(listOfTasks);
}

Вы сделали какое-либо профилирование, чтобы проверить, что на самом деле работает медленно? Если это какой-то API, который вы запрашиваете, вы, вероятно, получите лучшую производительность с меньшими усилиями, если запрос позволит вам получать данные для нескольких автомобилей одновременно.

JonasH 16.05.2022 22:55

@JonasH Каждая итерация извлекает данные с защитного IP-адреса. это не очень медленно. что я имею в виду. Он извлекается с IP-адреса 1, проверяя детали соединения, затем второй IP-адрес начинается после завершения IP 1 ... и так далее, вместо этого я хотел бы, чтобы IP 1 и 2 начали обработку одновременно

Dev 16.05.2022 22:59

Как метод item.GetIsConnected() связан со свойством item.IsConnected?

Theodor Zoulias 16.05.2022 22:59

@TheodorZoulias item.GetIsConnected() обновляет item.IsConnected

Dev 16.05.2022 23:01

Поэтому, если вы вызовете IsConnected до завершения асинхронного GetIsConnected(), вы можете получить неверный результат. Что делает свойство IsConnected ненадежным, я прав?

Theodor Zoulias 16.05.2022 23:05

@TheodorZoulias да.

Dev 16.05.2022 23:08
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
6
41
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Поскольку вы не ожидаете вызова GetIsConnected() в вашем примере ПОСЛЕ, цикл будет продолжаться, и значение не будет сравниваться с тем, что было бы после завершения вызова GetIsConnected(), я думаю, что вы хотели бы сделать, это добавить еще один метод с типом возвращаемого значения Task и пусть метод вызывает GetIsConnected() и await его внутри метода, а затем вызывает GetCarDetailsAsync() при необходимости:

//changed to return type of Task, as async void should be avoided
//unless this is an event handler method
private async Task Refresh()
//private async void Refresh() //change to this if event handler
{
    List<Task> listOfTasks = new List<Task>();
    foreach (var item in Cars.ToList<Carnet>())
    {
        listOfTasks.Add(GetCarDetails(item));        
    }
    await Task.WhenAll(listOfTasks).ConfigureAwait(false);
}

//method to await the call to GetIsConnect() 
//and then call GetCarDetailsAsync() if necessary
private async Task GetCarDetails(Carnet c)
{
    await c.GetIsConnected();
    if (c.IsConnected)
    {
        await c.GetCarDetailsAsync();
    }
}

Другие вопросы по теме