异步流?

Async Stream 简单说来是一种非同步的迭代器模式,说更白一点就是可以await 的foreach。在过去的C# 中如果要回传一个可迭代的IEnumerable<T> ,我们可能会这样写:

    public class EnumerableProcess
{
async static public Task<IEnumerable<string>> ReadLineAsync(string path)
{
List<string> list = new List<string>();
using (StreamReader reader = File.OpenText(path))
{
while (await reader.ReadLineAsync() is string result)
{
list.Add(result);
await Task.Delay(100);
}
}
return list;
}
}

  这是一个非同步一行一行读取文字档的例子,这个例子里的回传型别是一个Task<IEnumerable<string>>   ,外部程式码将会这样呼叫这个方法:

 var r = await EnumerableProcess.ReadLineAsync(path);
foreach (var item in r)
{
Console.WriteLine(item);
}

  

这造成一个长时等待的问题,因为呼叫端必须等待ReadLineAsync 这个Task 整个完成后才能回传;所以C# 8.0 引入了Async Stream 使得非同步的迭代得以实现, 这件事情不仅仅牵涉到编译器,也需要一些新的型别,主要是以下三个:

(1) IAsyncDisposable -- IAsyncEnumerator<out T> 将会拓展这个介面

public interface IAsyncDisposable
{
ValueTask DisposeAsync();
}

(2)IAsyncEnumerator <out T>

public interface IAsyncEnumerator<out T> : IAsyncDisposable
{
T Current { get; } ValueTask<bool> MoveNextAsync();
}

(3)IAsyncEnumerable <out T>

public interface IAsyncEnumerable<out T>
{
IAsyncEnumerator<T> GetAsyncEnumerator();
}

实作Async Stream

由于此时在框架中对于整个Async Stream 的实作尚未完整,所以没办法直接使用yield return,先示范最基本的写法,建立一个类别,并且实作以上介面:

    sealed class AsyncFileProcess : IAsyncEnumerable<string>, IAsyncEnumerator<string>
{
private readonly StreamReader _reader; private bool _disposed;
public AsyncFileProcess(string path)
{
_reader = File.OpenText(path);
_disposed = false;
} public string Current { get; private set; }
public IAsyncEnumerator<string> GetAsyncEnumerator()
{
return this;
}
async public ValueTask<bool> MoveNextAsync()
{
await Task.Delay(100);
var result = await _reader.ReadLineAsync();
Current = result;
return result != null;
} async public ValueTask DisposeAsync()
{
await Task.Run(() => Dispose());
} private void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
} private void Dispose(bool disposing)
{
if (!this._disposed)
{
if (_reader != null)
{
_reader.Dispose();
}
_disposed = true;
}
}
}

呼叫端就可以这样呼叫它:

var process = new AsyncFileProcess("SourceFile.txt");
try
{
await foreach (var s in process)
{
Console.WriteLine(s);
} Console.ReadLine();
}
finally
{
await process.DisposeAsync();
}

你可以感受到第一个例子是停顿了很久之后,蹦一下全跳出来;而第二的例子则会一行行跑出来(为了强化这个效果在两方都加了Task.Delay )。在第二个例子的呼叫端可以看到await foreach 的使用。

C# 8.0 抢先看-- Async Stream的更多相关文章

  1. 【转】【C#】C# 5.0 新特性——Async和Await使异步编程更简单

    一.引言 在之前的C#基础知识系列文章中只介绍了从C#1.0到C#4.0中主要的特性,然而.NET 4.5 的推出,对于C#又有了新特性的增加--就是C#5.0中async和await两个关键字,这两 ...

  2. 转:[你必须知道的异步编程]C# 5.0 新特性——Async和Await使异步编程更简单

    本专题概要: 引言 同步代码存在的问题 传统的异步编程改善程序的响应 C# 5.0 提供的async和await使异步编程更简单  async和await关键字剖析 小结 一.引言 在之前的C#基础知 ...

  3. [你必须知道的异步编程]C# 5.0 新特性——Async和Await使异步编程更简单

    本专题概要: 引言 同步代码存在的问题 传统的异步编程改善程序的响应 C# 5.0 提供的async和await使异步编程更简单  async和await关键字剖析 小结 一.引言 在之前的C#基础知 ...

  4. [译] C# 5.0 中的 Async 和 Await (整理中...)

    C# 5.0 中的 Async 和 Await [博主]反骨仔 [本文]http://www.cnblogs.com/liqingwen/p/6069062.html 伴随着 .NET 4.5 和 V ...

  5. Android P新功能特性抢先看

    2018年3月8日,Google推出了Android P Preview版本,并提供官方镜像下载. 为了让广大开发者能够及时了解Android P的新功能特性,提前为您的app进行良好适配,WeTes ...

  6. 四、C# 5.0 新特性——Async和Await使异步编程更简单

    一.引言 .NET 4.5 的推出,对于C#又有了新特性的增加--就是C#5.0中async和await两个关键字,这两个关键字简化了异步编程,之所以简化了,还是因为编译器给我们做了更多的工作,下面就 ...

  7. [转帖]CentOS 8.0.1905 和CentOS Stream(滚动发行)正式发布

    CentOS 8.0.1905 和CentOS Stream(滚动发行)正式发布 https://zhuanlan.zhihu.com/p/84001292 还发现openssl 的 版本太高 不兼容 ...

  8. C#5.0 异步编程 Async和Await--异步方法的规范和注意事项

    要些异步方法要注意一下几点: 异步方法的返回值有三种: 1.没有任何返回值的void 2.返回一个Task任务的Task,可以获得该异步方法的执行状态 3.返回Task<T> 可以获得异步 ...

  9. 【转】OpenStack奥斯汀峰会Keynotes国内抢先看

    http://www.openstack.cn/?p=5341 OpenStack奥斯汀峰会Keynotes国内抢先看入口:http://www.tudou.com/home/_903780397/i ...

随机推荐

  1. 生信工具汇总--OMICtools

    各种生信工具: https://omictools.com/

  2. vue--vant组件库field输入框

    安装vant UI框架: cnpm install vant –-save-dev 导入组件-在main.js里: import Vant from 'vant'; import'vant/lib/v ...

  3. vivo 1805的usb调试模式在哪里,开启vivo 1805usb调试模式的流程

    经常我们使用安卓手机通过数据线连接上PC的时候,如果手机没有开启usb调试模式,PC则没办法成功识别我们的手机,部分软件也没办法正常使用,此情况我们需要找方法将手机的usb调试模式打开,下面我们讲解v ...

  4. 如何让写得html页面自动刷新

    一:新建一个文件夹用vscode打开 二:终端输入npm init 然后一路回车会在文件夹中生成一个package.json文件 三:新建个html,在终端中输入cnpm install -g liv ...

  5. 数据流中的中位数 Find Median from Data Stream

    2019-04-17 16:34:50 问题描述: 问题求解: class MedianFinder { PriorityQueue<Integer> smaller; PriorityQ ...

  6. Oracle高级查询之over(partition by...)

    现有表,数据如下: eg1:查询年龄第二的队员 通常写法: select * from (select a.*, rownum r from (select t.* from l_student_in ...

  7. 结对编程四则运算--JAVA实现(徐静、林文敏)

    Github项目地址 项目相关要求 -n 参数控制生成题目的个数 (√) Myapp.exe -n 10 // 将生成10个题目 -r 参数控制题目中数值(自然数.真分数和真分数分母)的范围 (√) ...

  8. 小程序一个大盒子里面的盒子内容居中对其显示wxss写法

    对小程序研究感兴趣的可加(交流QQ群:604788754)入群联系群主可得到小程序教学资源. 这个案例只是想展示效果,内容部分未进行for循环绑定处理: WXML: <view class=&q ...

  9. Spark基本架构

    Spark基本架构图如下: Client:客户端进程,负责提交作业. Driver:一个Spark作业有一个spark context,一个Spark  Context对应一个Driver进程,作业的 ...

  10. lr_场景设计之组场景、nmon监控

    1.组场景常用于回归 ,可以设置成一个脚本后多久运行下一个脚本: Real-world Schedule和Basic schedule的区别:根据官方文档,这两种模式下,场景中的每个虚拟用户组(可看成 ...