C#异步迭代 IAsyncEnumerable 应用
最近用WPF做金税盘开发中有这样一个需求,批量开票每次开票都需要连接一次金税盘。
比如我有发票 a, b ,c ,d e 这五张发票,每次开具发票都需要调用金税盘底层,才能正常开票。
首先,尝试写第一个方法
private void Button_Click(object sender, RoutedEventArgs e)
{
var dateStart = DateTime.Now; //记录用时的起始时间
DebugText = string.Empty;
List<string> fpList = new List<string>() { "a", "b", "c", "d" }; foreach (var item in MockIO)
{
var dateEnd = DateTime.Now;
var timeSpan = dateEnd - dateStart;//记录开票用时
DebugText += item + " " + timeSpan.TotalSeconds + "\r\n"; }
} /// <summary>
/// 批量开票方法
/// </summary>
/// <param name="ls"></param>
/// <returns></returns>
public static IEnumerable<string> MockIO(List<string> ls)
{ foreach (var item in ls)
{
Task.Delay(1000).Wait();
yield return item;
Debug.WriteLine(Thread.GetCurrentProcessorId());
}
}
来看效果

很明显,发生了UI阻塞情况。因为我们并未对代码做任何异步处理。接下来,我们开始尝试修改。
首先,我们尝试按照常规异步方法修改 MockIO 函数,增加 async 关键词,返回结果增加 Task, 内部对IO操作添加 await。
修改完毕后,编译并没有通过,VS对该方法报异常

通过提示信息,我们可以发现,返回值 Task<IEnumerable<string>> 并不是可以迭代的,因为我们采用了 yield 来返回值,所以我们需要一个可以迭代的返回值。
比如改成这样

但是,这样一次就返回一组 Task ,没有用到方便的 yield;
此时,就可以用到 IAsyncEnumerable 来设计了,IAsyncEnumerable是C# 8.0引入的新特性,在异步迭代中,非常方便。如上述代码,可以直接修改为
public static async IAsyncEnumerable<string> MockIOAsync(List<string> ls)
{
foreach (var item in ls)
{
Task<Task<string>> task = Task<Task<string>>.Factory.StartNew(async () =>
{
await Task.Delay(1000);
return item; }); yield return await task.Result;
}
}
我们再运行调试,看一下效果

我们可以看到,不仅UI没有被阻塞,同时,传回的值也是一个接一个的传过来的,符合我们的预期。
扩展:虽然上述步骤我们完成的UI的非阻塞的实现,但是我们整个开票用时并没有节省。
接下来,我将继续修改 MockIOAsync 方法,将实现迭代器内部的多线程操作。
修改后的代码如下
public static async Task<IEnumerable<string>> MockIOPerformanceAsync(List<string> ls)
{
List<string> lss = new List<string>();
List<Task> tasks = new List<Task>();
foreach (var item in ls)
{ Task task = new Task(() =>
{
Task.Delay(1000).Wait();
Debug.WriteLine(Thread.GetCurrentProcessorId());
lss.Add(item);
});
tasks.Add(task);
task.Start(); }
foreach (var item in tasks)
{
await item;
}
return lss;
}
效果展示:

嗯,速度很快,但是排序乱了,因为此方法在遍历中新建了线程,list 添加并不保证按照迭代器的顺序添加。有得有失。
自动判断
中文
中文(简体)
中文(香港)
中文(繁体)
英语
日语
朝鲜语
德语
法语
俄语
泰语
南非语
阿拉伯语
阿塞拜疆语
比利时语
保加利亚语
加泰隆语
捷克语
威尔士语
丹麦语
第维埃语
希腊语
世界语
西班牙语
爱沙尼亚语
巴士克语
法斯语
芬兰语
法罗语
加里西亚语
古吉拉特语
希伯来语
印地语
克罗地亚语
匈牙利语
亚美尼亚语
印度尼西亚语
冰岛语
意大利语
格鲁吉亚语
哈萨克语
卡纳拉语
孔卡尼语
吉尔吉斯语
立陶宛语
拉脱维亚语
毛利语
马其顿语
蒙古语
马拉地语
马来语
马耳他语
挪威语(伯克梅尔)
荷兰语
北梭托语
旁遮普语
波兰语
葡萄牙语
克丘亚语
罗马尼亚语
梵文
北萨摩斯语
斯洛伐克语
斯洛文尼亚语
阿尔巴尼亚语
瑞典语
斯瓦希里语
叙利亚语
泰米尔语
泰卢固语
塔加路语
茨瓦纳语
土耳其语
宗加语
鞑靼语
乌克兰语
乌都语
乌兹别克语
越南语
班图语
祖鲁语
自动选择
中文
中文(简体)
中文(香港)
中文(繁体)
英语
日语
朝鲜语
德语
法语
俄语
泰语
南非语
阿拉伯语
阿塞拜疆语
比利时语
保加利亚语
加泰隆语
捷克语
威尔士语
丹麦语
第维埃语
希腊语
世界语
西班牙语
爱沙尼亚语
巴士克语
法斯语
芬兰语
法罗语
加里西亚语
古吉拉特语
希伯来语
印地语
克罗地亚语
匈牙利语
亚美尼亚语
印度尼西亚语
冰岛语
意大利语
格鲁吉亚语
哈萨克语
卡纳拉语
孔卡尼语
吉尔吉斯语
立陶宛语
拉脱维亚语
毛利语
马其顿语
蒙古语
马拉地语
马来语
马耳他语
挪威语(伯克梅尔)
荷兰语
北梭托语
旁遮普语
波兰语
葡萄牙语
克丘亚语
罗马尼亚语
梵文
北萨摩斯语
斯洛伐克语
斯洛文尼亚语
阿尔巴尼亚语
瑞典语
斯瓦希里语
叙利亚语
泰米尔语
泰卢固语
塔加路语
茨瓦纳语
土耳其语
宗加语
鞑靼语
乌克兰语
乌都语
乌兹别克语
越南语
班图语
祖鲁语
有道翻译
百度翻译
谷歌翻译
谷歌翻译(国内)
翻译 朗读 复制 正在查询,请稍候…… 重试 朗读 复制 复制 朗读 复制 via 百度翻译 译
自动判断
中文
中文(简体)
中文(香港)
中文(繁体)
英语
日语
朝鲜语
德语
法语
俄语
泰语
南非语
阿拉伯语
阿塞拜疆语
比利时语
保加利亚语
加泰隆语
捷克语
威尔士语
丹麦语
第维埃语
希腊语
世界语
西班牙语
爱沙尼亚语
巴士克语
法斯语
芬兰语
法罗语
加里西亚语
古吉拉特语
希伯来语
印地语
克罗地亚语
匈牙利语
亚美尼亚语
印度尼西亚语
冰岛语
意大利语
格鲁吉亚语
哈萨克语
卡纳拉语
孔卡尼语
吉尔吉斯语
立陶宛语
拉脱维亚语
毛利语
马其顿语
蒙古语
马拉地语
马来语
马耳他语
挪威语(伯克梅尔)
荷兰语
北梭托语
旁遮普语
波兰语
葡萄牙语
克丘亚语
罗马尼亚语
梵文
北萨摩斯语
斯洛伐克语
斯洛文尼亚语
阿尔巴尼亚语
瑞典语
斯瓦希里语
叙利亚语
泰米尔语
泰卢固语
塔加路语
茨瓦纳语
土耳其语
宗加语
鞑靼语
乌克兰语
乌都语
乌兹别克语
越南语
班图语
祖鲁语
自动选择
中文
中文(简体)
中文(香港)
中文(繁体)
英语
日语
朝鲜语
德语
法语
俄语
泰语
南非语
阿拉伯语
阿塞拜疆语
比利时语
保加利亚语
加泰隆语
捷克语
威尔士语
丹麦语
第维埃语
希腊语
世界语
西班牙语
爱沙尼亚语
巴士克语
法斯语
芬兰语
法罗语
加里西亚语
古吉拉特语
希伯来语
印地语
克罗地亚语
匈牙利语
亚美尼亚语
印度尼西亚语
冰岛语
意大利语
格鲁吉亚语
哈萨克语
卡纳拉语
孔卡尼语
吉尔吉斯语
立陶宛语
拉脱维亚语
毛利语
马其顿语
蒙古语
马拉地语
马来语
马耳他语
挪威语(伯克梅尔)
荷兰语
北梭托语
旁遮普语
波兰语
葡萄牙语
克丘亚语
罗马尼亚语
梵文
北萨摩斯语
斯洛伐克语
斯洛文尼亚语
阿尔巴尼亚语
瑞典语
斯瓦希里语
叙利亚语
泰米尔语
泰卢固语
塔加路语
茨瓦纳语
土耳其语
宗加语
鞑靼语
乌克兰语
乌都语
乌兹别克语
越南语
班图语
祖鲁语
有道翻译
百度翻译
谷歌翻译
谷歌翻译(国内)
翻译 朗读 复制 正在查询,请稍候…… 重试 朗读 复制 复制 朗读 复制 via 百度翻译 译
C#异步迭代 IAsyncEnumerable 应用的更多相关文章
- ES6-11学习笔记--异步迭代
ES9提供异步迭代: for await of Symbol.asyncIterator function getPromise(time) { return new Promise((resol ...
- C# 8 中的异步迭代器 IAsyncEnumerable<T> 解析
异步编程已经流行很多年了,.NET 引入的 async 和 await 关键词让异步编程更具有可读性,但有一个遗憾,在 C# 8 之前都不能使用异步的方式处理数据流,直到 C# 8 引入的 IAsyn ...
- 一文说通C#中的异步迭代器
今天来写写C#中的异步迭代器 - 机制.概念和一些好用的特性 迭代器的概念 迭代器的概念在C#中出现的比较早,很多人可能已经比较熟悉了. 通常迭代器会用在一些特定的场景中. 举个例子:有一个for ...
- ES6 Generators的异步应用
ES6 Generators系列: ES6 Generators基本概念 深入研究ES6 Generators ES6 Generators的异步应用 ES6 Generators并发 通过前面两篇文 ...
- 深入Asyncio(十)异步解析式
Async Comprehensions 目前已经学会了如何在Python中进行异步迭代,接下来的问题是这是否适用于解析式?答案是OJBK!该支持在PEP 530中提及,建议去读一下. >> ...
- [译]Python中的异步IO:一个完整的演练
原文:Async IO in Python: A Complete Walkthrough 原文作者: Brad Solomon 原文发布时间:2019年1月16日 翻译:Tacey Wong 翻译时 ...
- 【JS】336- 拆解 JavaScript 中的异步模式
点击上方"前端自习课"关注,学习起来~ JavaScript 中有很多种异步编程的方式.callback.promise.generator.async await 甚至 RxJS ...
- 【JS】285- 拆解 JavaScript 中的异步模式
JavaScript 中有很多种异步编程的方式.callback.promise.generator.async await 甚至 RxJS.我最初接触不同的异步模式时,曾想当然的觉得 promise ...
- 聊一聊C# 8.0中的await foreach
AsyncStreamsInCShaper8.0 很开心今天能与大家一起聊聊C# 8.0中的新特性-Async Streams,一般人通常看到这个词表情是这样. 简单说,其实就是C# 8.0中支持aw ...
随机推荐
- Jmeter(四十四) - 从入门到精通高级篇 - Jmeter远程启动(本地运行+远程运行)(详解教程)
1.简介 这篇文章其实很简单,就是为下一篇文章做一个铺垫,所以宏哥给小伙伴或童鞋们提前热身一下. 2.什么是远程运行? 远程执行,就是脚本放在本地,执行却在另一台电脑上执行,当然,可以是远程多台电脑一 ...
- systemd服务的输出重定向到指定文件
有一种更优雅的方法可以解决systemd输出到指定文件而非/var/log/message,需要使用systemd参数与rsyslog过滤器.并指示syslog过滤器按程序名称拆分其输出. syste ...
- [bug] IDEA:application context not configured for this file
参考 https://blog.csdn.net/a772304419/article/details/79680833
- [bug] Scala eclipse:找不到或无法加载主类
原因 混合java 和scala 无法编译 解决 右键项目 > properties > scala Compiler >勾选Use Project Setting > Sca ...
- LTP--linux稳定性测试 linux性能测试 ltp压力测试 内核更新 稳定性测试
LTP--linux稳定性测试 linux性能测试 ltp压力测试 zhangzj1030关注14人评论33721人阅读2011-12-09 12:07:45 说明:在写这篇文章之前,本人也不曾了 ...
- linux中级之防火墙的数据传输过程
网络数据传输过程 netfilter在数据包必须经过且可以读取规则的位置,共设有5个控制关卡.这5个关卡处的检查规则分别放在5个规则链中(有的叫钩子函数(hook functions).也就是说5条链 ...
- gpgj - 06.估值分析举例
06.估值分析举例 1.举个栗子-贵州茅台的护城河 品牌效益高 只有高档产品 不卖中低档,不会拉低公司收入 { "question": "我们来复习一下护城河要如何分 ...
- WPF 2D图形 Shape入门(一)--Shape
本文是篇WPF Shape的入门文章 Shape 首先看看shape的继承链关系: 一个Shape具有哪些重要属性: 属性 说明 DefiningGeometry 默认的几何形状 RenderedGe ...
- gitlab使用URL导入远程仓库报错
gitlab使用URL导入远程仓库报错Import url is blocked: Only allowed ports are 80,443, and any over 1024 报错内容为Impo ...
- [leetcode] 875. 爱吃香蕉的珂珂(周赛)
875. 爱吃香蕉的珂珂 这题时间要求比较严格... 首先,将piles排序,然后二分查找. 总之,答案K肯定位于piles[?]piles[?+1]或者1piles[0]之间 所以我们先二分把?找到 ...