我正在逐步将 Ix.NET 引入到遗留项目中。 我有许多返回Task<IEnumerable<T>>
的存储级 API,但我想使它们适应IAsyncEnumerable<T>
以便在系统的其余部分使用。 似乎应该有一个辅助方法(对于 IEnumerable 来说.ToAsyncEnumerable()
(来帮助解决这个问题,但我找不到任何东西...... 我是否必须实现自己的自定义枚举器? (不难,但我不想重新发明轮子(
Task<IEnumerable<T>> GetSomeResults<T>()
{
throw new NotImplementedException();
}
async IAsyncEnumerable<T> GetAsyncEnumerable<T>()
{
var results = await GetSomeResults<T>();
foreach(var item in results)
{
yield return item;
}
}
正如Theodor Zoulias所评论的那样,System.Linq.Async 是来自 .NET Foundation 的 NuGet 包,它支持 ToAsyncEnumerable()
。
用法示例:
var tasks = new Task[0]; // get your IEnumerable<Task>s
tasks.ToAsyncEnumerable();
如果你在谈论 Web API,Task<IEnumerable<T>>
是一种生成IEnumerable<T>
的异步方式。
无论同步还是异步生成IEnumerable<T>
,整个列表都将作为 HTTP 响应发送。
在客户端上利用IAsyncEnumerable<T>
的方法是,如果该客户端正在调用某种流式处理或向服务器发出多个请求以获取唯一的结果列表(分页(。
public static async IAsyncEnumerable<T> ToAsyncEnumerable<T>(this IEnumerable<T> enumerable)
{
using IEnumerator<T> enumerator = enumerable.GetEnumerator();
while (await Task.Run(enumerator.MoveNext).ConfigureAwait(false))
{
yield return enumerator.Current;
}
}
我正在寻找完全相同的东西,由于这里的回复,我假设确实没有像AsAsyncEnumerable()
这样的方法。所以这就是我最终做的事情,也许它可以帮助其他人:
public static class AsyncEnumerableExtensions {
public struct AsyncEnumerable<T> : IAsyncEnumerable<T> {
private readonly IEnumerable<T> enumerable;
public AsyncEnumerable(IEnumerable<T> enumerable) {
this.enumerable = enumerable;
}
public IAsyncEnumerator<T> GetAsyncEnumerator(CancellationToken cancellationToken = new CancellationToken()) {
return new AsyncEnumerator<T>(enumerable?.GetEnumerator());
}
}
public struct AsyncEnumerator<T> : IAsyncEnumerator<T> {
private readonly IEnumerator<T> enumerator;
public AsyncEnumerator(IEnumerator<T> enumerator) {
this.enumerator = enumerator;
}
public ValueTask DisposeAsync() {
enumerator?.Dispose();
return default;
}
public ValueTask<bool> MoveNextAsync() {
return new ValueTask<bool>(enumerator == null ? false : enumerator.MoveNext());
}
public T Current => enumerator.Current;
}
public static AsyncEnumerable<T> AsAsyncEnumerable<T>(this IEnumerable<T> that) {
return new AsyncEnumerable<T>(that);
}
public static AsyncEnumerator<T> AsAsyncEnumerator<T>(this IEnumerator<T> that) {
return new AsyncEnumerator<T>(that);
}
}