一、異步枚舉

异步枚举器(Async Enumerator)是指一种异步迭代器,可以用于处理异步数据源。它允许我们以异步的方式逐个读取数据源中的元素。

在传统的同步枚举器中,当我们遍历一个集合时,程序会等待每个元素返回后才能继续执行下一个操作。而在异步枚举器中,我们可以在等待当前元素返回时同时执行其他操作。

异步枚举器通常使用 async/await 关键字来实现异步操作。例如,在 C# 中,我们可以使用以下代码创建一个异步枚举器:

public async IAsyncEnumerator<int> GetAsyncEnumerator(CancellationToken cancellationToken = default)
{
for (int i = 0; i < 10; i++)
{
await Task.Delay(1000, cancellationToken); // 模拟异步操作
yield return i;
}
}

通过上述代码,我们可以创建一个异步枚举器,其中每隔1秒钟返回一个整数。在使用这个异步枚举器时,我们可以使用 await foreach 语法进行遍历:

await foreach (var item in GetAsyncEnumerator())
{
Console.WriteLine(item);
}

这将输出从0到9的整数,并且在每次等待延迟期间不会阻塞主线程,因为异步枚举器的枚举操作是异步执行的。

二、異步並行枚舉器

并行异步枚举器是一种用于处理大量数据集合的工具,它能够同时处理多个项并在必要时异步返回结果。下面是一个示例代码,用于演示如何创建并行异步枚举器:

public async Task<IEnumerable<T>> ParallelAsyncEnumerator<T>(
IEnumerable<Task<T>> source, int degreeOfParallelism)
{
var enumerator = source.GetEnumerator();
var tasks = new List<Task<T>>(degreeOfParallelism);
for (int i = 0; i < degreeOfParallelism; i++)
{
if (!enumerator.MoveNext())
{
break;
}
tasks.Add(enumerator.Current);
}
while (tasks.Count > 0)
{
var completedTask = await Task.WhenAny(tasks);
tasks.Remove(completedTask);
if (enumerator.MoveNext())
{
tasks.Add(enumerator.Current);
}
yield return completedTask.Result;
}
}

是不是有些惱火,沒關係,兄弟,給你加上註釋

点击查看代码
// 定义了一个异步方法 ParallelAsyncEnumerator,该方法使用泛型参数 T,接受两个参数
// 参数1:一个 IEnumerable<Task<T>> 类型的集合,包含了一组需要并行执行的 Task 对象
// 参数2:一个整数类型的 degreeOfParallelism,表示最大并发数
public async Task<IEnumerable<T>> ParallelAsyncEnumerator<T>(
IEnumerable<Task<T>> source, int degreeOfParallelism)
{
// 获取 source 的枚举器对象
var enumerator = source.GetEnumerator();
// 创建一个空的 Task 列表 tasks,用于存储正在执行的任务
var tasks = new List<Task<T>>(degreeOfParallelism);
// 循环 degreeOfParallelism 次,如果还有未处理的任务,则将其添加到 tasks 中
for (int i = 0; i < degreeOfParallelism; i++)
{
// 如果已经没有未处理的任务,则退出循环
if (!enumerator.MoveNext())
{
break;
}
// 将当前枚举器指向的 Task 添加到 tasks 中
tasks.Add(enumerator.Current);
}
// 当存在正在执行的任务时进行遍历,直至所有的任务都执行完毕
while (tasks.Count > 0)
{
// 等待任意一个 Task 执行完成
var completedTask = await Task.WhenAny(tasks);
// 将已完成的任务从 tasks 列表中移除
tasks.Remove(completedTask);
// 如果仍然存在未处理的任务,则将其添加到 tasks 列表中
if (enumerator.MoveNext())
{
tasks.Add(enumerator.Current);
}
// 返回已完成的任务的结果
yield return completedTask.Result;
}
}

这里的 ParallelAsyncEnumerator 方法接受两个参数:源集合 source 和并行度 degreeOfParallelism。该方法首先创建一个枚举器,然后使用 degreeOfParallelism 创建若干个任务,并从枚举器中获取前 degreeOfParallelism 个元素赋值给这些任务。接下来,在一个 while 循环中,该方法通过 Task.WhenAny 等待任意一个任务完成,并将已完成的任务从任务列表中移除。如果枚举器还有剩余元素,则获取下一个元素,并将其作为新任务添加到任务列表中。最后,通过 yield return 返回已完成任务的结果。

使用并行异步枚举器,可以同时处理多个任务,从而提高程序的效率。例如,在下载大量文件时,可以使用并行异步枚举器同时下载多个文件,从而加速整个过程。

《C# in depth》第5章C#5.0中的更改(十三)——異步枚舉器的更多相关文章

  1. 第四章 在MVC4.0中对脚本以及样式表的引用变化

    原文:http://www.cnblogs.com/xdotnet/archive/2012/07/21/aspnet40_webpage20.html 一.可以直接使用“~”,而无需使用Href对象 ...

  2. Introduction to 3D Game Programming with DirectX 12 学习笔记之 --- 第七章:在Direct3D中绘制(二)

    原文:Introduction to 3D Game Programming with DirectX 12 学习笔记之 --- 第七章:在Direct3D中绘制(二) 代码工程地址: https:/ ...

  3. 《Entity Framework 6 Recipes》中文翻译系列 (20) -----第四章 ASP.NET MVC中使用实体框架之在MVC中构建一个CRUD示例

    翻译的初衷以及为什么选择<Entity Framework 6 Recipes>来学习,请看本系列开篇 第四章  ASP.NET MVC中使用实体框架 ASP.NET是一个免费的Web框架 ...

  4. 编写高质量代码:改善Java程序的151个建议(第一章:JAVA开发中通用的方法和准则)

    编写高质量代码:改善Java程序的151个建议(第一章:JAVA开发中通用的方法和准则) 目录 建议1: 不要在常量和变量中出现易混淆的字母 建议2: 莫让常量蜕变成变量 建议3: 三元操作符的类型务 ...

  5. NodeJs>------->>第二章:Node.js中交互式运行环境--------REL

    第二章:Node.js中交互式运行环境--------REL 一:REPL运行环境概述 C:\Users\junliu>node > foo = 'bar' ; 'bar' > 二: ...

  6. ANTLR4权威指南 - 第6章 尝试一些实际中的语法

    第6章 尝试一些实际中的语法 在前一章,我们学习了通用词法结构和语法结构,并学习了如何用ANTLR的语法来表述这些结构.现在,是时候把我们学到的这些用来构建一些现实世界中的语法了.我们的主要目标是,怎 ...

  7. “全栈2019”Java第九十七章:在方法中访问局部内部类成员详解

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ...

  8. “全栈2019”Java第八十五章:实现接口中的嵌套接口

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ...

  9. “全栈2019”Java第二十七章:流程控制语句中循环语句for

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ...

  10. “全栈2019”Java第二十六章:流程控制语句中循环语句do-while

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ...

随机推荐

  1. JS-1基本语法

    初识JavaScript JavaScript是一种运行在客户端的脚本语言 脚本语言:不需要编译,运行过程中由js解释器(js引擎)逐行来进行解释并执行 现在也可以基于Node.js技术进行服务器编程 ...

  2. 数据处理(传值& 乱码)

    处理前端提交的数据 1.提交的域名称和处理方法的参数名一致时    /hello?name=akagi @RequestMapping("/hello") public Strin ...

  3. Apollo3-Blue-MCU芯片典型硬件电路解析

    一 芯片简介 1.简介 Apollo3 Blue Wireless SoC是一款超低功耗无线mcu芯片,它的运行功耗降至6μA/ MHz以下.该器件采用ARM Cortex M4F内核,运行频率高达9 ...

  4. [leetcode 496. 下一个更大元素 I] 单调栈

    单调栈的写法: import java.util.ArrayDeque; import java.util.Deque; import java.util.HashMap; import java.u ...

  5. 4项关键技术提升 XR 扩展现实体验-XR应用云流化

    无论是使用户能够协作设计电动赛车,还是帮助观众通过数字世界与自然互动,越来越多的企业利用XR扩展现实为用户提供沉浸式逼真的虚拟环境. 下一代沉浸式技术的应用越来越广泛,图形和人工智能的最新突破正在扩展 ...

  6. SQLI-LABS(Less-11、12)

    Less-11(POST-Error Based-Single Quotes-String) 打开Less-11的页面,可以看到一个登录框,需要输入用户名和密码,由本关名字可知SQL语句是单引号闭合. ...

  7. 记录-因为写不出拖拽移动效果,我恶补了一下Dom中的各种距离

    这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助 背景 最近在项目中要实现一个拖拽头像的移动效果,一直对JS Dom拖拽这一块不太熟悉,甚至在网上找一个示例,都看得云里雾里的,发现遇到最大 ...

  8. PDF的分割与合并

    1.进行PDF切割 python代码如下: # 20220521 # 1.选择要分割的文件 # 2.选择要保存的位置,分割为多个文件时,可自动用页码命名 # 3.输入要分割的页码,可以是一个范围1-2 ...

  9. css实现按钮点击水波纹效果和两边扩散效果

    废话少说,先上代码了,复制到html中即可使用 点击查看代码 <!DOCTYPE html> <html lang="en"> <head> & ...

  10. 使用maven命令 创建基于Scala的flink项目

    windows下 mvn archetype:generate ^ -DarchetypeGroupId=org.apache.flink ^ -DarchetypeArtifactId=flink- ...