Foreach异步C#

时间:2019-06-14 08:38:09

标签: c# async-await

想象一下,我有一个具有相同异步方法的类的列表,我可以在列表上分别进行操作:

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

但我也可以:

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

在这种情况下,不再需要我的测试方法是异步的。 但是这两种方法会产生相同的效果吗?

2 个答案:

答案 0 :(得分:1)

据我所知,相当于您编写的代码(异步运行程序=>等待运行程序.Test())将是

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

因此,您不会等待Do方法(它是异步void),而在第一个版本中,您实际上仅在上一个结束之后才执行下一个任务。

  

我的测试方法不再需要异步

我认为它看起来像是因为在任何地方都没有显式的异步void,如果您使用命名方法重写它,将会更容易看到。

答案 1 :(得分:1)

区别是:


您可以等待第一种情况下返回的任务,第二种情况下等待“解雇”:

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()); }
    });
}

看起来不太好。

在第一种情况下,每个任务都等待上一个任务的开始,而在第二种情况下,则不是(感谢Scott Chamberlain在评论中纠正了我)。