Foreach асинхронный c # - PullRequest
       13

Foreach асинхронный c #

0 голосов
/ 14 июня 2019

Представьте, что у меня есть список классов с одинаковым асинхронным методом, который я могу использовать в этом списке:

public async Task Test()
{
    foreach (var runner in _runners)
    {
        await runner.Test();
    }
}

но я также могу сделать:

public void Test()
{
    _runners.ForEach(async runner => await runner.Test());
}

В этом случае мой метод тестирования больше не должен быть асинхронным. Но будут ли эти 2 метода одинаковыми?

Ответы [ 2 ]

1 голос
/ 14 июня 2019

Различия:


Вы можете подождать, пока задание вернется в первом случае, и «запустить и забыть» во втором:

public async void TestCaller()
{
    await Test();
    // do things after all runners completed
}

Когда вы звоните async void метод вы должны обрабатывать исключения самостоятельно, или они будут проглочены.Вы должны переписать второй случай, например:

public void Test()
{
    _runners.ForEach(async runner => {
        try { await runner.Test(); }
        catch (Exception e) { Console.Writeln(e.ToString()); }
    });
}

Это выглядит не очень хорошо.

Также каждая задача в первом случае ожидает начала предыдущего конца, а во втором случае - нет.(спасибо Скотту Чемберлену, который исправил меня в комментариях).

1 голос
/ 14 июня 2019

Ну, как я понимаю, эквивалент кода, который вы написали (async runner => await runner.Test ()), будет

public static async void Do(Runner r)
{
        await r.Test();
}

И, следовательно, вы не будете ждать метода Do (он асинхронный void), тогда как в первой версии вы фактически выполняете следующую задачу только после того, как предыдущая закончилась.

Мой метод испытаний больше не должен быть асинхронным

Я думаю, что это выглядит просто потому, что нигде нет явной асинхронной пустоты, если переписать ее именованными методами, это будет легче увидеть.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...