C# 8.0 抢先看-- Async Stream
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的更多相关文章
- 【转】【C#】C# 5.0 新特性——Async和Await使异步编程更简单
一.引言 在之前的C#基础知识系列文章中只介绍了从C#1.0到C#4.0中主要的特性,然而.NET 4.5 的推出,对于C#又有了新特性的增加--就是C#5.0中async和await两个关键字,这两 ...
- 转:[你必须知道的异步编程]C# 5.0 新特性——Async和Await使异步编程更简单
本专题概要: 引言 同步代码存在的问题 传统的异步编程改善程序的响应 C# 5.0 提供的async和await使异步编程更简单 async和await关键字剖析 小结 一.引言 在之前的C#基础知 ...
- [你必须知道的异步编程]C# 5.0 新特性——Async和Await使异步编程更简单
本专题概要: 引言 同步代码存在的问题 传统的异步编程改善程序的响应 C# 5.0 提供的async和await使异步编程更简单 async和await关键字剖析 小结 一.引言 在之前的C#基础知 ...
- [译] C# 5.0 中的 Async 和 Await (整理中...)
C# 5.0 中的 Async 和 Await [博主]反骨仔 [本文]http://www.cnblogs.com/liqingwen/p/6069062.html 伴随着 .NET 4.5 和 V ...
- Android P新功能特性抢先看
2018年3月8日,Google推出了Android P Preview版本,并提供官方镜像下载. 为了让广大开发者能够及时了解Android P的新功能特性,提前为您的app进行良好适配,WeTes ...
- 四、C# 5.0 新特性——Async和Await使异步编程更简单
一.引言 .NET 4.5 的推出,对于C#又有了新特性的增加--就是C#5.0中async和await两个关键字,这两个关键字简化了异步编程,之所以简化了,还是因为编译器给我们做了更多的工作,下面就 ...
- [转帖]CentOS 8.0.1905 和CentOS Stream(滚动发行)正式发布
CentOS 8.0.1905 和CentOS Stream(滚动发行)正式发布 https://zhuanlan.zhihu.com/p/84001292 还发现openssl 的 版本太高 不兼容 ...
- C#5.0 异步编程 Async和Await--异步方法的规范和注意事项
要些异步方法要注意一下几点: 异步方法的返回值有三种: 1.没有任何返回值的void 2.返回一个Task任务的Task,可以获得该异步方法的执行状态 3.返回Task<T> 可以获得异步 ...
- 【转】OpenStack奥斯汀峰会Keynotes国内抢先看
http://www.openstack.cn/?p=5341 OpenStack奥斯汀峰会Keynotes国内抢先看入口:http://www.tudou.com/home/_903780397/i ...
随机推荐
- krpano生成全景图
1.下载krpano工具 第一次我下载的有水印,但是第二次下载的便没了,原因我也不清楚.下载好后不要急着打开.exe程序 2.生成全景图 将全景图拖入MAKE VTUOR (NORMAL) DROPL ...
- CopyOnWriteArrayList与Collections.synchronizedList的性能对比(转)
列表实现有ArrayList.Vector.CopyOnWriteArrayList.Collections.synchronizedList(list)四种方式. 1 ArrayList Array ...
- kotlin 委托
委托模式是软件设计模式中的一项基本技巧.在委托模式中,有两个对象参与处理同一个请求,接受请求的对象将请求委托给另一个对象来处理. Kotlin 直接支持委托模式,更加优雅,简洁.Kotlin 通过关键 ...
- Oracle创建表、修改字段类型
1.创建表 1.创建表 create table SCM_PER( --SCM_PER表名 ID ) primary key,--主键ID USERID ),--用户ID --Permission v ...
- 【安卓进阶】LiveData
最近参与到后端的工作中,虽然以前在工作中使用过PHP,但是这次使用的是Java,开发思路和方式有所不同.后端开发中,做接口也是需要处理大量的业务逻辑关系,同时一些事务之类的技术因素也要考虑好,在架设项 ...
- [数据算法]D1.BloomFilter
BloomFilter是一种高效的去重算法,算法的要义是散列对比. 1.原理 当一个元素加入集合时,判断这个元素是否 2.举例 例如我要对URL去重(这个在爬虫上可以用): URL1 -> 3. ...
- 雷林鹏分享:jQuery EasyUI 数据网格 - 自定义分页
jQuery EasyUI 数据网格 - 自定义分页 数据网格(datagrid)内置一个很好特性的分页功能,自定义也相当简单.在本教程中,我们将创建一个数据网格(datagrid),并在分页工具栏上 ...
- 【转】 HDMI介绍与流程
转自:https://www.cnblogs.com/TaigaCon/p/3840653.html HDMI,全称为(High Definition Multimedia Interface)高清多 ...
- Android Satudio的使用记录
Satudio的使用记录之导入新项目: Satudio导入项目的心得[基本分为4步完成]1.需要保证自己的satudio中项目能够运行,同时找到该工作空间的和项目的各个参数 {项目-->右键—— ...
- Nginx启动,证书报错SSL_CTX_use_PrivateKey_file.....
报错nginx: [emerg] SSL_CTX_use_PrivateKey_file("/etc/nginx/ssl/myxxxxgame201904.key") failed ...