Take() 方法如何与 IAsyncEnumerable 配合使用

问题描述 投票:0回答:1

我最近一直在玩 IAsyncEnumerables,有一点我无法理解它在幕后是如何工作的。

考虑以下代码:

private async Task Test()
{
    var t = new List<int>();

    await foreach (var number in Numbers().Take(5).ConfigureAwait(false))
    {
        t.Add(number);
    }
}

int[] myIntArray = new int[10] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};

private async IAsyncEnumerable<int> Numbers()
{
    foreach (var element in myIntArray)
    {
        yield return element;
    }
}

所以困扰我的是,IAsyncEnumerable方法如何知道如何只执行5次,或者换句话说,它如何翻译.Take(5)方法,使其可以获取传递的数字执行时考虑到?

c# .net async-await .net-6.0 iasyncenumerable
1个回答
0
投票

IAsyncEnumerable<T>
是一个简单的接口,定义了单一方法 -
IAsyncEnumerable<T>.GetAsyncEnumerator(CancellationToken)
返回
IAsyncEnumerator<T>
,这并没有那么复杂 - 它有
MoveNextAsync
方法,可以将枚举器异步前进到下一个元素集合的
Current
属性,获取集合中枚举数当前位置的元素,类似于“普通”
IEnumerable<T>
。简而言之,所有 LINQ 方法都将与这两个方法一起运行(如果我们不考虑对某些极端情况的优化)。

据我所知,没有框架为异步枚举提供 LINQ 方法。如果您使用的是 反应扩展

 中的 
System.Linq.Async 中的一个,那么它的实现方式与“普通”
Take
基本相同,它将源枚举包装到具有重载的
MoveNext
的特殊“分区器”类中
。对于异步枚举,它是
AsyncEnumerablePartition
,它基本上会调用
await MoveNextAsync(...)
,直到达到请求的限制(即传递到
Take
),然后停止执行。

© www.soinside.com 2019 - 2024. All rights reserved.