嵌套的异步lambda未被等待

4
以下代码在迭代时没有返回完整的集合。每次运行返回的数组长度都是随意的。出了什么问题?
以下代码无法返回完整的集合。每次运行返回的数组长度都是随意的。出了什么问题?
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());
}

以下代码使用新的异步 MongoDB C# 驱动程序。
public async Task Iterate(Action<TDocument> processor)
{
    await _collection.Find<TDocument>(_ => true).ForEachAsync(processor);
}

1
“Iterate” 是如何定义的? - Yuval Itzchakov
2个回答

5
你看到任意数量的值的原因在于 Iterate 接收了一个类型为 Action<T> 的委托,它等同于 async void,从而使得这个执行方式成为“fire-and-forget”风格。
内部方法实际上并不知道已经传递给它一个异步委托,因此它在不实际等待每个项完成的情况下迭代集合。
相反,你需要做的是将方法参数更改为类型为 Func<TDocument, Task> 的委托 并使用适当的 ForEachAsync 重载
public Task Iterate(Func<TDocument, Task> processor)
{
    return _collection.Find<TDocument>(_ => true).ForEachAsync(processor);
}

您可以在这里看到源代码

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

0

你创建线程并启动它们。从那时起,你就不知道会发生什么。但你的代码下一步是返回,所以你在赌这些线程将比主线程更快地执行。

在正常的线程场景中,你将加入线程,这些线程正在向包中添加项目。其中一个加入是线程等待其他线程执行,因此仍然是异步的,但在完成所有操作之前等待返回。

这在这里得到了完美的解释:http://www.dotnetperls.com/thread-join


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接