《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第 ...
随机推荐
- java项目-尚硅谷项目三员工调度系统
导入工具类和数据 创建TeamSchedule项目,com.atguigu.team. view,com.atguigu.team.service,com.atguigu.team.domain包 , ...
- 基于python的json和cvs格式转换
一 概念 1 json: JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式. 易于人阅读和编写.同时也易于机器解析和生成. 它基于JavaScript Pr ...
- Elasticsearch(es) 查询语句语法详解
Elasticsearch 查询语句采用基于 RESTful 风格的接口封装成 JSON 格式的对象,称之为 Query DSL.Elasticsearch 查询分类大致分为全文查询.词项查询.复合查 ...
- YAML语法入门
Ansible是一个系列文章,我会尽量以通俗易懂.诙谐幽默的总结方式给大家呈现这些枯燥的知识点,让学习变的有趣一些. Ansible系列博文直达链接:Ansible入门系列 前言 在学习playboo ...
- MySQL(视图、事务、存储过程、函数、流程控制、索引)
一 视图(了解) 什么是视图 视图就是通过查询得到一张虚拟表,然后保存下来,下次可以直接使用 为什么要用视图 如果要频繁的操作一张虚拟表(拼表组成的),你就可以制作成视图,后续直接操作 视图其实也是一 ...
- 崩溃bug日志总结3
目录介绍 1.1 OnErrorNotImplementedException[ Can't create handler inside thread that has not called Loop ...
- 记录--组件库的 Table 组件表头表体是如何实现同步滚动?
这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助 前言 在使用 Vue 3 组件库 Naive UI 的数据表格组件 DataTable 时碰到的问题,NaiveUI 的数据表格组件 Da ...
- 记录--vue+three,制作iview大波浪特效
这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助 一.效果图 具体效果可参考iview官方界面iView - 一套高质量的UI组件库 大波浪效果,使用的是three.js的官方例子,需要先 ...
- 01-【HAL库】STM32实现串口打印
一.什么是串口 串口通讯(Serial Communication)是一种设备间非常常用的串行通讯方式,因为它简单便捷,因此大部分电子设备都支持该通讯方式,电子工程师在调试设备时也经常使用该通讯方式输 ...
- 数字电路之MOS设计
数字电路之MOS设计 1.MOS的基本性质 MOS,即场效应管,四端器件,S.D.G.B四个端口可以实现开和关的逻辑状态,进而实现基本的逻辑门.NMOS和PMOS具有明显的对偶特性:NMOS高电平打开 ...