异步流?

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. springboot2.0配置连接池(hikari、druid)

    springboot2.0配置连接池(hikari.druid) 原文链接:https://www.cnblogs.com/blog5277/p/10660689.html 原文作者:博客园--曲高终 ...

  2. js if判断示例

    ){ ){ console.log("%0 pass") }else{ $(,v,function() { fla=; }); } }){ ){ console.log(" ...

  3. C++_day8pm_多态

    1.什么是多态 2. 示例代码: #include <iostream> using namespace std; //形状:位置.绘制 //+--圆形:半径.(绘制) //+--矩形:长 ...

  4. System.InvalidOperationException:“线程间操作无效: 从不是创建控件“btnSearch”的线程访问它。

    System.InvalidOperationException:“线程间操作无效: 从不是创建控件“btnSearch”的线程访问它.”这个问题属于跨线程问题 在Form1重载中写上一行代码 Sys ...

  5. OpenGL.Tutorial15_Lightmaps

    ZC:撤销 & 重做 — Blender Manual.html(https://docs.blender.org/manual/zh-hans/dev/interface/undo_redo ...

  6. http协议详解及htt面试题目,常见的http状态码

    http协议详解及htt面试题目,常见的http状态码 HTTP报文是面向文本的,报文中的每一个字段都是一些ASCII码串,各个字段的长度是不确定的.HTTP有两类报文:请求报文和响应报文. HTTP ...

  7. Vue-CLI3.0版本配置BootStrap的方法

    一.引入jquery bootstrap popper   用   cnpm install jquery bootstrap@3 popper.js --save  用cnpm 来导入 用npm会出 ...

  8. C++之标准库map

    目录 1.成员函数 2.元素访问 3.迭代器Iterators(C++ 11) 4.容量Capacity 5.修改函数(C++ 11和C++ 17) 6.查找表Lookup 7.观察Observers ...

  9. Word中如何删除目录页的页码

    ---恢复内容开始--- word中插入目录之后想要为每页添加页码,如果我们直接添加页码的话会出现目录是第一页,正文部分的页码是从2开始而不是1,用下面的方法就可以解决 首先让文档中的所有符号可见 第 ...

  10. 微信小程序1rpx border ios真机显示不全问题

    无意间测试发现,把border的颜色的透明度颜色改成0.99就可以了.1就不行. 边框显示不全的写法: border:1rpx solid rgba(244,84,80,1); 将边框代码的透明度改成 ...