Страницы

Поиск по вопросам

воскресенье, 29 декабря 2019 г.

Как параллельно выполнять функции на C#?

#c_sharp #async_await


При запросе пользователя я хочу произвести несколько запросов к БД и потом вывести ответ.
Но, если я использую 

async
await- Function1    
await- Function2  
await- Function3  
"склеить ответ функций и перевести в json"  
вывести ответ....  


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


Ответы

Ответ 1



Попробуйте через Task.WhenAll: Task first = Function1(); Task second = Function2(); Task third = Function3(); await Task.WhenAll(first, second, third);

Ответ 2



Для параллельного выполнения асинхронных функций нужно воспользоваться методом Task.WhenAll(): var fooTask = FooAsync(); var barTask = BarAsync(); var gazTask = GazAsync(); await Task.WhenAll(fooTask, barTask, gazTask); После того, как все задачи завершатся, к результатам (если они есть) можно обратиться с помощью await или свойства Result: var fooResult = await fooTask; var barResult = barTask.Result; var gazResult = await gazTask; Стоит также упомянуть обработку исключений. Если вы не обрабатываете их в каждом из методов, то Task.WhenAll(), естественно, пробрасывает их наверх. Особенность заключается в том, что если Task.WhenAll() ожидается с помощью ключевого слова await, наверх выбрасывается первое случившееся исключение. В такой ситуации c тасками нужно обращаться аккуратнее: мы не знаем, какой из них завершился с ошибкой, а какой вообще еще не завершился. Поэтому нужны предварительные проверки с использованием свойствa IsFaulted/Status. var fooTask = FooAsync(); var barTask = BarAsync(); var gazTask = GazAsync(); try { await Task.WhenAll(fooTask, barTask, gazTask); } catch (Exception e) { if (fooTask.IsFaulted) { // ошибка в FooAsync() } else if (barTask.IsFaulted) { // ошибка в BarAsync() } else if (gazTask.IsFaulted) { // ошибка в GazAsync() } } Если же вы делаете блокирующее ожидание (Task.WhenAll().Wait()) или используете блокирующий аналог (Task.WaitAll()), то все произошедшие исключение помещаются внутрь AggregateException. Проверка, какие таски завершились ошибкой, а какие еще не завершились, остается той же.

Комментариев нет:

Отправить комментарий