问题描述
我有一个返回 IAsyncEnumerable
的函数。我想await
完成它,但我不关心任何结果。我只关心调用函数的副作用。
如何在不使用 for 循环或将其转换为容器(例如 await
)的情况下轻松地 IAsyncEnumerable
ToListAsync
完成?
解决方法
您可以使用 LastOrDefaultAsync
包中的 System.Linq.Async 运算符,然后使用 AsTask
扩展方法将结果 ValueTask<T>
转换为 Task
。为了更加方便,您可以将这两个操作合并为一个扩展方法 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
包中的 System.Interactive.Async 运算符来防止这种情况发生,但我认为这太麻烦了。
简短回答:你不能。
Loger 回答:询问
如何在不使用 for 循环或将其转换为容器(例如 ToListAsync)的情况下轻松等待 IAsyncEnumerable 完成?
就像在问
如何在不使用 await
或类似 .Result
或 .Wait()
的情况下等待任务完成?
知道 IAsyncEnumerable
何时完成的方法是在其迭代器上调用 await MoveNextAsync()
并返回 false
。最简洁的方法是
await foreach (var _ in AsyncGenerator()) ; // The semicolon is necessary