gpt4 book ai didi

c# - 在 Action 中使用带有 await 的 ForEachAsync 时不等待

转载 作者:太空狗 更新时间:2023-10-30 00:31:09 26 4
gpt4 key购买 nike

下面应该返回“C”,但它返回“B”

using System.Data.Entity;
//...
var state = "A";
var qry = (from f in db.myTable select f);
await qry.ForEachAsync(async (myRecord) => {
await DoStuffAsync(myRecord);
state = "B";
});
state = "C";
return state;

它不等待 DoStuffAsync 完成,state="C" 运行完毕,然后 state="B" 执行(因为它内部仍在等待).

最佳答案

那是因为 ForEachAsync 的实现不等待委托(delegate)操作

moveNextTask = enumerator.MoveNextAsync(cancellationToken);
action(current);

参见 https://github.com/mono/entityframework/blob/master/src/EntityFramework/Infrastructure/IDbAsyncEnumerableExtensions.cs#L19

但那是因为,您不能等待一个 Action ,委托(delegate)需要是一个返回任务的 Func - 参见 How do you implement an async action delegate method?

因此,在 Microsoft 提供包含 Func 委托(delegate)并使用 await 调用它的签名之前,您必须推出自己的扩展方法。我目前正在使用以下内容。

public static async Task ForEachAsync<T>(
this IQueryable<T> enumerable, Func<T, Task> action, CancellationToken cancellationToken) //Now with Func returning Task
{
var asyncEnumerable = (IDbAsyncEnumerable<T>)enumerable;
using (var enumerator = asyncEnumerable.GetAsyncEnumerator())
{

if (await enumerator.MoveNextAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false))
{
Task<bool> moveNextTask;
do
{
var current = enumerator.Current;
moveNextTask = enumerator.MoveNextAsync(cancellationToken);
await action(current); //now with await
}
while (await moveNextTask.ConfigureAwait(continueOnCapturedContext: false));
}
}
}

有了这个,您 OP 中的原始测试代码将按预期工作。

关于c# - 在 Action 中使用带有 await 的 ForEachAsync 时不等待,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29787098/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com