异步与yield

发布时间 2023-12-26 23:54:35作者: 茜茜87

1.yield

迭代器中使用 yield 语句提供下一个值或表示迭代结束。

yield return:在迭代中提供下一个值

yield break:显式示迭代结束

迭代器的执行:当开始对迭代器的结果进行迭代时,迭代器会一直执行,直到到达第一个 yield return 语句为止。 然后,迭代器的执行会暂停,调用方会获得第一个迭代值并处理该值。 在后续的每次迭代中,迭代器的执行都会在导致上一次挂起的 yield return 语句之后恢复,并继续执行,直到到达下一个 yield return 语句为止。 当控件到达迭代器或 yield break 语句的末尾时,迭代完成。

如以下示例所示:

var numbers = ProduceEvenNumbers(5);
Console.WriteLine("Caller: about to iterate.");
foreach (int i in numbers)
{
    Console.WriteLine($"Caller: {i}");
}

IEnumerable<int> ProduceEvenNumbers(int upto)
{
    Console.WriteLine("Iterator: start.");
    for (int i = 0; i <= upto; i += 2)
    {
        if(i<5)
        {
        Console.WriteLine($"Iterator: about to yield {i}");
        yield return i;
        Console.WriteLine($"Iterator: yielded {i}");
        }
        else
            yield break;
    }
    Console.WriteLine("Iterator: end.");
}
// Output:
// Caller: about to iterate.
// Iterator: start.
// Iterator: about to yield 0
// Caller: 0
// Iterator: yielded 0
// Iterator: about to yield 2
// Caller: 2
// Iterator: yielded 2
// Iterator: about to yield 4
// Caller: 4
// Iterator: yielded 4

 

2.异步中的yield

yield return 不仅能简化数据的返回,而且可以让数据处理“流水线化”,提升性能。

asyncs是提示编译器为异步方法中的await代码进行分段处理的,而一个异步方法是否修饰为async对于方法的调用者而言没有区别,抽象方法不能修饰为async。

C#8.0之前,async方法中不能用yield(两个都是分段处理)。8.0开始,把返回值声明为IAsyncEnumerable,然后遍历的时候用await foreach()即可。

static async Task Main(string[] args)
{
    await foreach (var value in Test())
    {
        Console.WriteLine(value);
    }       
}

static async IAsyncEnumerable<string> Test()
{
    yield return "11";
    yield return "22";
    yield return "33";
}
//执行结果:
//11
//22
//33