📜  协程层出不穷——C#(1)

📅  最后修改于: 2023-12-03 15:07:20.430000             🧑  作者: Mango

协程层出不穷——C#

协程是一种可以暂停执行,稍后再继续执行的过程,并且在暂停时可以保留上下文的机制。在C#中,协程被称为迭代器(Iterator)。通过使用迭代器,我们可以写出更加简洁、清晰的异步代码,并且使代码具有更好的可读性。

迭代器的定义

在C#中,迭代器是一种特殊的方法,可以用yield关键字返回一个序列中的元素,而不需要将整个序列都计算出来。迭代器方法定义了一个返回IEnumerable或IEnumerable对象的方法,其中T是元素的类型。

下面是一个简单的示例,演示了如何使用迭代器来遍历一个整数数组:

public static IEnumerable<int> GetNumbers()
{
    int[] numbers = new int[] { 1, 2, 3, 4, 5 };
    foreach (int number in numbers)
    {
        yield return number;
    }
}
迭代器的使用

在使用迭代器时,我们可以使用foreach语句来遍历序列中的元素。在迭代器中,每次调用yield return会返回序列中下一个元素,并在此处暂停执行,直到下一次迭代开始。

下面是一个演示迭代器使用的示例,它将异步读取文件的逻辑以同步的方式展示,但实际上仍然是异步执行的:

public static IEnumerable<string> ReadLines(string path)
{
    using (StreamReader reader = new StreamReader(path))
    {
        string line;
        while ((line = reader.ReadLine()) != null)
        {
            yield return line;
        }
    }
}

在上面的代码中,ReadLines方法并不会立即读取整个文件,而是等到foreach语句第一次运行时才会读取第一行。然后,每当调用yield return时,它会暂停执行,直到下一次迭代开始。

迭代器的进阶使用

除了基础用法之外,我们还可以使用迭代器来实现复杂的异步操作。下面是一个示例,演示了如何使用迭代器来实现异步等待:

public static IEnumerable<Task> WaitAllAsync(IEnumerable<Task> tasks)
{
    List<Task> taskList = new List<Task>(tasks);
    while (taskList.Count > 0)
    {
        int index = Task.WaitAny(taskList.ToArray());
        Task completedTask = taskList[index];
        taskList.RemoveAt(index);
        yield return completedTask;
    }
}

在上面的代码中,使用Task.WaitAny方法来等待所有的任务。每当有一个任务完成时,我们就会通过yield return返回这个已经完成的任务。通过在等待时停止执行并保留上下文,我们可以使代码看起来更加简洁和清晰。

结论

通过使用迭代器,我们可以将异步操作包装成一种更加可读和易于理解的方式,并且简化了代码的复杂性。C#中的迭代器提供了一种优雅的方式来处理协作异步任务。