《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第 ...
随机推荐
- 多线程系列(十八) -AQS原理浅析
一.摘要 在之前的文章中,我们介绍了 ReentrantLock.ReadWriteLock.CountDownLatch.CyclicBarrier.Semaphore.ThreadPoolExec ...
- autohotkey 设置快捷键 设置光标位置 (ctrl + alt + Numpad0)
autohotkey 设置快捷键 设置光标位置 (ctrl + alt + Numpad0) 原因 3个屏幕,所以鼠标设置的灵敏度非常高,经常就找不到鼠标在哪了. 设置个快捷键,让鼠标每次都初始化一个 ...
- 发现这个ip有bt下载,所以改路由,让其访问到一个不存在的ip上 route add
管理员权限cmd 发现这个ip有bt下载,所以改路由,让其访问到一个不存在的ip上 route add -p 195.154.181.225 mask 255.255.255.255 127.0.0. ...
- ubuntu下安装numpy和scipy正确方法
1.numpy NumPy(Numeric Python)是用Python进行科学计算的基本软件包. NumPy是Python编程语言的扩展,增加了对大型多维数组和矩阵的支持,以及一个大型的高级数学函 ...
- 泰凌微TLSR8258芯片解决方案开发之串口打印级别设置
一 TRSR8258简介 该芯片是泰凌微推出来的一款纯ble的芯片,接口丰富,功耗低,资源丰富,非常适合做可穿戴物联网设备,笔者拿这颗芯片做了不少方案,感觉非常好用,所以这里写一下使用心得. 二 串 ...
- decltype总结
decltype会识别const和引用 decltype一个表达式的时候会判断该表达式是左值还是右值,如果是左值就返回引用,否则就返回非引用. int &a = xx; const declt ...
- 三维模型3DTile格式轻量化压缩必要性分析
三维模型3DTile格式轻量化压缩必要性分析 理解3DTile格式轻量化压缩的必要性,首先需要理解三维模型的复杂性和数据量.三维模型通常包含大量的顶点.面片和纹理信息,这使得其数据量非常大,尤其对于大 ...
- Matlab绘图(1)通过属性检查器调整绘图
Matlab图形属性检查器 和其他语言的绘图不一样的是,Matlab允许我们通过非编程的方式来自定义调整绘图.下面介绍Matlab图形的构成以及几种调整绘图时的常用操作. 图形构成 什么是Figure ...
- [Java]基本数据类型与引用类型赋值的底层分析的小结
[版权声明]未经博主同意,谢绝转载!(请尊重原创,博主保留追究权) https://www.cnblogs.com/cnb-yuchen/p/17969159 出自[进步*于辰的博客] 目录 1.关于 ...
- 《Spring6核心源码解析》已完结,涵盖IOC容器、AOP切面、AOT预编译、SpringMVC,面试杠杠的!
作者:冰河 博客:https://binghe.gitcode.host 文章汇总:https://binghe.gitcode.host/md/all/all.html 源码地址:https://g ...