Tod*_*odd 4 .net c# asynchronous entity-framework async-await
以下应返回"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;
Run Code Online (Sandbox Code Playgroud)
它不等待DoStuffAsync完成,state="C"运行然后state="B"执行(因为它内部仍在等待).
那是因为ForEachAsync的实现不等待委托操作
moveNextTask = enumerator.MoveNextAsync(cancellationToken);
action(current);
Run Code Online (Sandbox Code Playgroud)
但那是因为,你不能等待一个动作,委托需要是一个返回任务的Func - 请参阅如何实现异步动作委托方法?
因此,在Microsoft提供包含Func委托的签名并使用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));
}
}
}
Run Code Online (Sandbox Code Playgroud)
这样,OP中的原始测试代码将按预期工作.
| 归档时间: |
|
| 查看次数: |
7602 次 |
| 最近记录: |