如何在丢弃结果时等待 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 包来防止这种情况发生,但我认为它变得太麻烦了。
我有一个 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 包来防止这种情况发生,但我认为它变得太麻烦了。