IAsyncEnumerable可以来实现异步迭代,本文就主要介绍了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 添加并不保证按照迭代器的顺序添加。有得有失。
到此这篇关于C#异步迭代IAsyncEnumerable应用实现的文章就介绍到这了,更多相关C#异步迭代IAsyncEnumerable内容请搜索得得之家以前的文章希望大家以后多多支持得得之家!
本文标题为:C#异步迭代IAsyncEnumerable应用实现
基础教程推荐
- 一个读写csv文件的C#类 2022-11-06
- C# windows语音识别与朗读实例 2023-04-27
- linux – 如何在Debian Jessie中安装dotnet core sdk 2023-09-26
- C# List实现行转列的通用方案 2022-11-02
- C#控制台实现飞行棋小游戏 2023-04-22
- C#类和结构详解 2023-05-30
- winform把Office转成PDF文件 2023-06-14
- unity实现动态排行榜 2023-04-27
- ZooKeeper的安装及部署教程 2023-01-22
- C# 调用WebService的方法 2023-03-09