如何同步 运行 异步枚举器方法并将其存储为 IEnumerable?

How can I run a async enumerator method synchronously and store it as an IEnumerable?

我有一个使用 yield returns IAsyncEnumerable 的异步方法。在某些情况下,可能需要同步获取项目,因此我想为此创建另一种方法,即 returns IEnumerable by 运行 同步现有方法以避免重复代码。

async IAsyncEnumerable<Foo> GetItemsAsync()
{
    yield return ...
}

IEnumerable<Foo> GetItems() => GetItemsAsync() // Run shyncronously

我阅读了很多关于 运行 异步方法的解决方案,使用 Task.RunSynchronously 等技术同步异步方法,或者只是在同步上下文中调用它并忽略警告。但是,在异步枚举的情况下,这些似乎都不可能。该接口没有 RunSynchronously 方法,尝试使用未等待的 foreach 枚举它会导致编译错误。同步获取枚举器和 运行 MoveNext 似乎也不是一个选项,因为该方法 returns ValueTask 不具有 Wait 方法,我需要捕获任务的结果以知道何时停止迭代。

那么是否可以同步强制我的异步枚举器方法并获得 IEnumerable 的结果,如果可以,怎么做?

您可以使用 ToEnumerable extension method from the System.Linq.Async 包。这个方法的签名是:

public static IEnumerable<TSource> ToEnumerable<TSource>(
    this IAsyncEnumerable<TSource> source)

...您可以这样使用它:

IEnumerable<Foo> GetItems() => GetItemsAsync().ToEnumerable();

更新:下一版本的 .NET 平台 (.NET 7) 中可能包含具有相同功能的扩展方法 ToBlockingEnumerable。相关 GitHub 问题:Add an IAsyncEnumerable.ToEnumerable extension method.