Ben*_* E. 4 c# lambda mongodb async-await
以下代码不会返回它正在迭代的整个集合。每次运行时返回的数组具有任意长度。怎么了?
public async Task<IHttpActionResult> GetClients()
{
var clientInfoCollection = new ConcurrentBag<ClientInfoModel>();
await _client.Iterate(async (client) =>
{
clientInfoCollection.Add(new ClientInfoModel
{
name = client.name,
userCount = await _user.Count(clientId)
});
});
return Ok(clientInfoCollection.ToArray());
}
Run Code Online (Sandbox Code Playgroud)
以下代码使用新的异步 MongoDB C# 驱动程序
public async Task Iterate(Action<TDocument> processor)
{
await _collection.Find<TDocument>(_ => true).ForEachAsync(processor);
}
Run Code Online (Sandbox Code Playgroud)
您看到任意数量的值的原因是事实上Iterate接收了一个 type 的委托Action<T>,它等效于async void,有效地使其成为“即发即忘”的执行风格。
内部方法实际上并不知道异步委托已传递给它,因此它迭代集合而不实际异步等待每个项目完成。
您需要做的是使方法参数成为类型的委托Func<TDocument, Task> 并使用正确的重载ForEachAsync:
public Task Iterate(Func<TDocument, Task> processor)
{
return _collection.Find<TDocument>(_ => true).ForEachAsync(processor);
}
Run Code Online (Sandbox Code Playgroud)
public static async Task ForEachAsync<TDocument>(
this IAsyncCursor<TDocument> source,
Func<TDocument, int, Task> processor,
CancellationToken cancellationToken = default(CancellationToken))
{
Ensure.IsNotNull(source, "source");
Ensure.IsNotNull(processor, "processor");
// yes, we are taking ownership... assumption being that they've
// exhausted the thing and don't need it anymore.
using (source)
{
var index = 0;
while (await source.MoveNextAsync(cancellationToken).ConfigureAwait(false))
{
foreach (var document in source.Current)
{
await processor(document, index++).ConfigureAwait(false);
cancellationToken.ThrowIfCancellationRequested();
}
}
}
}
Run Code Online (Sandbox Code Playgroud)