如何在丢弃结果时等待 IAsyncEnumerable

How to await an IAsyncEnumerable while discarding the results

我有一个 returns 和 IAsyncEnumerable 的函数。我想 await 它完成,但我不关心任何结果。我只关心调用函数的副作用

如何在不使用 for 循环或将其转换为容器(例如 ToListAsync)的情况下轻松 await 完成 IAsyncEnumerable

简答:你不能。


登录者回答:提问

How do can I easily await the IAsyncEnumerable for completion without using a for loop or turning it into a container (e.g. ToListAsync)?

就像在问

How can I wait for the completion of a Task without using await or something like .Result or .Wait()?

知道 IAsyncEnumerable 何时完成的方法是在其迭代器上调用 await MoveNextAsync() 并返回 false。最简洁的方法是

await foreach (var _ in AsyncGenerator()) ; // The semicolon is necessary

您可以使用 LastOrDefaultAsync operator from the System.Linq.Async package, and then convert the resulting ValueTask<T> to a Task by using the AsTask 扩展方法。为了更加方便,您可以将这两个操作组合到一个扩展方法 ToTask:

/// <summary>
/// Retrieves a Task object that represents the completion of this IAsyncEnumerable.
/// </summary>
public static Task ToTask<T>(this IAsyncEnumerable<T> source)
{
    return source.LastOrDefaultAsync().AsTask();
}

但老实说,手动执行循环更简单,而且效率可能更高:

public async static Task ToTask<T>(this IAsyncEnumerable<T> source)
{
    await foreach (var _ in source.ConfigureAwait(false)) { }
}

LastOrDefaultAsync 运算符将在可枚举的生命周期内将最后发出的元素保留在内存中,这可能会阻止该元素被及时垃圾回收。您可以通过在查询中包含 IgnoreElements operator from the System.Interactive.Async 包来防止这种情况发生,但我认为它变得太麻烦了。