.NET控件ReSharper:异步流– C#8中的新语言功能介绍

ReSharper是一个著名的代码生成工具,其能帮助Microsoft Visual Studio成为一个更佳的IDE。实质上,ReSharper特征可用于C#,VB.net,XML,Asp.net,XAML,和构建脚本。

ReSharper Ultimate 2019.2提供了对C#8.0的更好支持以及一些Navigation,Find Usages和调试器数据提示的更新。它还改善了启动时间,并为VS 2019中的“Per-Monitor DPI Awareness”模式提供了初始支持.C ++项目的索引更快,支持更多C ++ 20功能。点击查看更新详情!

ReSharper最新试用版

自从C#8系列的最后一部分以来已经有一段时间了,但是它来了!我们将继续通过新的语言功能进行探索,并深入到异步流中。

在本系列中,我们正在研究:

  • 指数,范围和空值分配

  • 切换表达式和基于模式的用法

  • 递归模式匹配

  • 异步流

  • 可空引用类型

异步编程是一种编程形式,它可以通过允许将耗时的工作(例如从 络下载数据)与主线程分离来防止阻塞我们的应用程序。对于我们的实现,原则上,它需要将回调传递给异步方法,该异步方法又会在完成工作后调用该回调。

在C#5中,引入了async和await关键字。这些从根本上改善了我们编写和使用异步方法的方式。基本上,与同步实现相比,我们的代码结构可以保持几乎相同,但是编译器接管了很多工作,将我们的代码重组为上述回调,以使其具有状态且无阻塞。但是,这仅适用于使用Task和Task<T>作为返回类型的void和单结果方法。

产生数据流的方法(又名IEnumerable<T>)被省去了,需要编写自定义代码。但是,此类要求非常普遍,例如考虑使用云应用程序,从IoT传感器收集数据或从数据库接收数据。,C#8和IAsyncEnumerable!

随着.NET 2.1标准的发布,引入了一组3个接口:  IAsyncDisposable,IAsyncEnumerable<T>和IAsyncEnumerator<T>。这些接口允许我们以某种方式表示的异步版本IEnumerable<T>,从而使用异步流:

public interface IAsyncDisposable{    ValueTask DisposeAsync();}public interface IAsyncEnumerable<out T>{    IAsyncEnumerator<T> GetAsyncEnumerator(CancellationToken token = default);}public interface IAsyncEnumerator<out T> : IAsyncDisposable{    ValueTask<bool> MoveNextAsync();    T Current { get; }}

为了IAsyncEnumerable<T>在各种情况下都能正常工作(如await在finally块中一样),我们还需要IDisposable接口的异步版本。您可能已经猜到了,它叫做IAsyncDisposable:

public interface IAsyncDisposable{    ValueTask DisposeAsync();}

从.NET Core SDK 3.0开始,实际上已经实现了这些类型,并且使用C#8 foreach,using可以将and 关键字作为前缀await与IAsyncEnumerableand IAsyncDisposable实例一起使用。

IAsyncEnumerable<T>实质上,迭代意味着获取下一个对象成为异步操作,而foreach主体成为我们的回调。只有当我们继续循环时,才会提取一个新项目(与调用相对break)。这基本上将这种方法标记为基于拉的方法。该await foreach语句还基于模式工作,这意味着它将与提供适当GetAsyncEnumerator方法但不实现IAsyncEnumerable<T>接口的任何类型一起工作。

让我们看看如何将这些添加项组合使用。好奇的开发人员绝对应该抓住机会,看看它的反编译代码:

static async Task Main(){    await foreach (var data in ReadAndNormalize())    {        Console.WriteLine(data);    }}static async IAsyncEnumerable<Data> ReadAndNormalize(    [EnumeratorCancellation] CancellationToken token = default){    while (!token.IsCancellationRequested)    {        var data = await ReadInputFromDevice();        var normalizedData = ConvertAndNormalize(data);        yield return normalizedData;    }}static async Task<byte[]> ReadInputFromDevice() { return default; }static Data ConvertAndNormalize(byte[] data) { return default; }struct Data { }

请注意,CancellationToken标记有一个EnumeratorCancellation属性。与JetBrains.Annotations包中的EnumeratorCancellation属性相似,该属性(包含在中System.Runtime.CompilerServices)将代码片段标记为其他魔术,这些魔术目前还无法用语言本身来表达。

如前所述,using语句现在也可以使用await关键字作为前缀。让我们一起来看看!

async Task WriteToFileAsync(string file){    await using (var fs = new FileStream(file, FileMode.CreateNew))    await using (var sw = new StreamWriter(fs))    {        await sw.WriteAsync("Hello C#8!");    }}

由于.NET标准2.1,两个所涉及的类型FileStream,并StreamWriter都实现IAsyncDisposable。这样就可以异步完成所有处理工作,例如刷新磁盘更改。

ReSharper和Rider能为我做什么/strong>

除了解析新的语言结构外,ReSharper和Rider还带来了其他一些有助于异步流工作的优点。

Rider最新试用版

从我们可以枚举的最明显的操作开始,foreach 后缀模板已更新为完成,await foreach直到有问题的枚举类型为IAsyncEnumerable<T>或匹配其模式:

标签:

声明:本站部分文章及图片源自用户投稿,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!

上一篇 2019年9月18日
下一篇 2019年9月18日

相关推荐

发表回复

登录后才能评论