《C# in depth》第5章C#5.0中的更改(十三)——異步枚舉器
一、異步枚舉
异步枚举器(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中的更改(十三)——異步枚舉器的更多相关文章
- 第四章 在MVC4.0中对脚本以及样式表的引用变化
原文:http://www.cnblogs.com/xdotnet/archive/2012/07/21/aspnet40_webpage20.html 一.可以直接使用“~”,而无需使用Href对象 ...
- Introduction to 3D Game Programming with DirectX 12 学习笔记之 --- 第七章:在Direct3D中绘制(二)
原文:Introduction to 3D Game Programming with DirectX 12 学习笔记之 --- 第七章:在Direct3D中绘制(二) 代码工程地址: https:/ ...
- 《Entity Framework 6 Recipes》中文翻译系列 (20) -----第四章 ASP.NET MVC中使用实体框架之在MVC中构建一个CRUD示例
翻译的初衷以及为什么选择<Entity Framework 6 Recipes>来学习,请看本系列开篇 第四章 ASP.NET MVC中使用实体框架 ASP.NET是一个免费的Web框架 ...
- 编写高质量代码:改善Java程序的151个建议(第一章:JAVA开发中通用的方法和准则)
编写高质量代码:改善Java程序的151个建议(第一章:JAVA开发中通用的方法和准则) 目录 建议1: 不要在常量和变量中出现易混淆的字母 建议2: 莫让常量蜕变成变量 建议3: 三元操作符的类型务 ...
- NodeJs>------->>第二章:Node.js中交互式运行环境--------REL
第二章:Node.js中交互式运行环境--------REL 一:REPL运行环境概述 C:\Users\junliu>node > foo = 'bar' ; 'bar' > 二: ...
- ANTLR4权威指南 - 第6章 尝试一些实际中的语法
第6章 尝试一些实际中的语法 在前一章,我们学习了通用词法结构和语法结构,并学习了如何用ANTLR的语法来表述这些结构.现在,是时候把我们学到的这些用来构建一些现实世界中的语法了.我们的主要目标是,怎 ...
- “全栈2019”Java第九十七章:在方法中访问局部内部类成员详解
难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ...
- “全栈2019”Java第八十五章:实现接口中的嵌套接口
难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ...
- “全栈2019”Java第二十七章:流程控制语句中循环语句for
难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ...
- “全栈2019”Java第二十六章:流程控制语句中循环语句do-while
难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ...
随机推荐
- 发布DDD脚手架到Maven仓库,IntelliJ IDEA 配置一下即可使用
作者:小傅哥 博客:https://bugstack.cn 项目:https://gaga.plus 沉淀.分享.成长,让自己和他人都能有所收获! 大家好,我是技术UP主,小傅哥. 这篇文章将帮助粉丝 ...
- C++ Qt开发:QNetworkAccessManager网络接口组件
Qt 是一个跨平台C++图形界面开发库,利用Qt可以快速开发跨平台窗体应用程序,在Qt中我们可以通过拖拽的方式将不同组件放到指定的位置,实现图形化开发极大的方便了开发效率,本章将重点介绍如何运用QNe ...
- es索引数据复制并增加条件和修改目标数据值
es操作同一个索引里数据的复制语法 复制数据: POST _reindex { "source": { "index": "source_index& ...
- SyntaxError: invalid property id(就是不支持ES6) (浏览器不支持对象...展开)
SyntaxError: invalid property id(就是不支持ES6) (浏览器不支持对象...展开) 火狐55以后支持
- modalError.vue 错误提示框 vue2 iview
需求 一个错误提示框,后台需要有换行,默认没有换行,做一个支持换行的全局错误提示函数. 注意 代码只展示原理,直接不能使用,里面有getAc,有需要参考 https://www.cnblogs.com ...
- vscode 创建 git tag,并推送到远程
Step. 1: 创建tag 左侧 源代码管理 右上角 ... 标记 -> 创建标记 输入tag名称 回车 输入tag描述 Step. 2: 查看tag 使用命令 git tag 查看当前所有的 ...
- github无法访问?vscode 无法使用github登录同步? 改 hosts 吧
一.无法访问 github.com ? 想要去 github.com 上拿来主义,结果访问不了,或者 npm 时一直失败? 是什么原因不用问,直接使用 https://tool.lu/ip/ 查询到 ...
- Ubuntu 16.04 配置NFS
PS:要转载请注明出处,本人版权所有. PS: 这个只是基于<我自己>的理解, 如果和你的原则及想法相冲突,请谅解,勿喷. 前置说明 本文作为本人csdn blog的主站的备份.(Bl ...
- 快速上手系列:JavaScript
第一章 基础语法 1 javascript 的简介 * 是基于对象和事件驱动的语言,应用于客户端. - 基于对象: ** 提供好了很多对象,可以直接拿过来使用 - 事件驱动: ** html 做网站静 ...
- 使用graphviz图形化展示路径(决策树用到此库)
问题:当出现错误 graphviz.backend.execute.ExecutableNotFound: failed to execute WindowsPath('dot'), make sur ...