C# 要列出的任何点<;T>;。ForEach()是否具有异步?

C# 要列出的任何点<;T>;。ForEach()是否具有异步?,c#,asynchronous,async-await,C#,Asynchronous,Async Await,我遇到了这段代码: items.ForEach(async item => { doSomeStuff(); await mongoItems.FindOneAndUpdateAsync(mongoMumboJumbo); await AddBlah(SqlMumboJumbo); }); 把它变成一个.forEach委托有什么意义,或者它只是一个普通的forEach循环?只要包含循环的函数是异步的,那么默认情况下是异步的 ForEach收到的代理是一

我遇到了这段代码:

items.ForEach(async item =>
{
     doSomeStuff();   
     await mongoItems.FindOneAndUpdateAsync(mongoMumboJumbo);
     await AddBlah(SqlMumboJumbo);
});

把它变成一个.forEach委托有什么意义,或者它只是一个普通的forEach循环?只要包含循环的函数是异步的,那么默认情况下是异步的

ForEach收到的代理是一个
操作

public void ForEach(操作)
这意味着,您在其中使用的任何异步委托都将有效地变成
异步void
方法。这些都是“先开火,然后忘记”的执行方式。这意味着您的foreach不会在继续调用列表中下一项的委托之前异步完成等待,这可能是不希望的行为

改用常规的
foreach


旁注-Eric Lippert,很棒的博客文章。

你不知道函数什么时候完成,也不知道函数的结果。如果在单独的任务中启动每个计算,则可以等待Task.whalll并解释结果,甚至可以捕获异常:

private async Task ActionAsync(T item)
{
    doSomeStuff();   
    await mongoItems.FindOneAndUpdateAsync(mongoMumboJumbo);
    await AddBlah(SqlMumboJumbo);
}

private async Task MyFunction(IEnumerable<T> items)
{
    try
    {
        foreach (var item in items)
        {
            tasks.Add( ActionAsync(item) )
        }
        // while all actions are running do something useful
        // when needed await for all tasks to finish:
        await Task.WhenAll(tasks);
        // interpret the result of each action using property Task.Result
    }
    catch (AggregateException exc)
    {
        ProcessAggregateException(exc);
    }
}
专用异步任务ActionAsync(T项)
{
doSomeStuff();
等待mongoItems.FindOneAndUpdateAsync(mongomumbojimbo);
等待AddBlah(SqlMumboJumbo);
}
专用异步任务MyFunction(IEnumerable项)
{
尝试
{
foreach(项目中的var项目)
{
添加(ActionAsync(项目))
}
//在所有操作运行时,执行一些有用的操作
//需要时,等待所有任务完成:
等待任务。何时(任务);
//使用属性Task.result解释每个操作的结果
}
捕获(聚合异常exc)
{
ProcessAggregateException(exc);
}
}

当您的任何任务引发异常时,将引发aggregateException。If包含所有任务引发的所有异常。

它比普通的
foreach
循环更干净、更不冗长。这正是我要寻找的。我现在使用该控制器方法的原因是多线程/线程试图使用相同的db上下文错误。我真的不完全理解-但对于委托,它尝试异步地遍历每个项,而不是按顺序?编辑:哈哈,我不是第一次在Eric的博客上看到C#了。我一得到答案就会回来接受,泰。回答得好!下面是OP的另一个有用链接:将代码从items.ForEach切换到ForEach循环似乎已经修复了我所有的异步错误。如果e2e以后出现故障,将进行更新,但似乎已修复。现在要完全理解它。。
private async Task ActionAsync(T item)
{
    doSomeStuff();   
    await mongoItems.FindOneAndUpdateAsync(mongoMumboJumbo);
    await AddBlah(SqlMumboJumbo);
}

private async Task MyFunction(IEnumerable<T> items)
{
    try
    {
        foreach (var item in items)
        {
            tasks.Add( ActionAsync(item) )
        }
        // while all actions are running do something useful
        // when needed await for all tasks to finish:
        await Task.WhenAll(tasks);
        // interpret the result of each action using property Task.Result
    }
    catch (AggregateException exc)
    {
        ProcessAggregateException(exc);
    }
}