异步流?

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. 本地连接属性:Internet协议版本4(TCP/IPv4)打开闪退解决办法

    1.命令窗口配置网络连接指定IP netsh interface ip set address "本地连接" static IP地址 子网掩码 默认网关 例:netsh inter ...

  2. kafka知识点

    一.为什么需要消息系统 1.解耦: 允许你独立的扩展或修改两边的处理过程,只要确保它们遵守同样的接口约束. 2.冗余: 消息队列把数据进行持久化直到它们已经被完全处理,通过这一方式规避了数据丢失风险. ...

  3. [python]html格式转md格式

    html格式转md格式 # 模块html2text pip install html2text/pip3 install html2text 测试: import html2text as ht te ...

  4. IE低版本 JSON.parse 和stringify 的兼容 (IE8以下)

    低版本的IE不支持JSON,JSON对象解析不是随着javascript产生的,找到一段兼容常用的JSON.parse和JSON.stringify的代码if (!window.JSON) {wind ...

  5. Spring Cloud ----> 几个组件的总结

    Spring Cloud Eureka 多个服务,对应多个Eureka Client 只有一个Eureka Server ,充当注册中心的角色每个Eureka Client 有ip 地址和端口号,它们 ...

  6. Error during generated code invocation: com.intellij.debugger.engine.evaluation.EvaluateException: Method threw 'java.lang.IllegalAccessError' exception.

    场景描述: 再从该数据库中读取数据进行处理的时候,需要将某个字段加入到一个动态的map中,然后需要对该map进行filter过滤,在执行过滤方法的时候报错 Error during generated ...

  7. 别让持续交付自动化交付bug

    你的连续交付能力用得还好吗,比如频繁发布移动或云应用的特性增强?还是恰好相反,快速发布了带漏洞的版本? - Joel Shore 连续交付能让交付流程跑得更快,但连续交付本身并不能为发布质量打包票.国 ...

  8. Oracle表空间的创建与删除

    ORACLE中,表空间是数据管理的基本方法,所有用户的对象要存放在表空间中,也就是用户有空间的使用权,才能创建用户对象.否则是不充许创建对象,因为就是想创建对象,如表,索引等,也没有地方存放,Orac ...

  9. SQL 基础学习(1):下载DB Browser for SQLite. 下载graphviz(为了使用Rails ERD的前提)出现❌,已debug.

    SQL is a standard language for storing, manipulating and retrieving data in databases. 关系型数据库:RDBMS( ...

  10. C语言函数声明什么时候可以省略,什么时候不能省?

    在学习C语言函数的时候,老师总会告诉我们函数要写声明,然后再定义.这是个稳健的做法.等我自己学习了其他高级语言以后,回头再来写C,突然就觉得函数要写声明有点麻烦.无意间发现有一次函数没写声明居然编译( ...