1 TaskCompletionSource介绍

TaskCompletionSource提供创建未绑定到委托的任务,任务的状态由TaskCompletionSource上的方法显式控制,以支持未来的操作传播到它创建的任务。

使用场景

EAP(基于事件的异步模式)转TAP(基于任务的异步模式)

 public static Task<string> DownloadStringAsync(Uri url)
{
var tcs = new TaskCompletionSource<string>();
var wc = new WebClient();
wc.DownloadStringCompleted += (s,e) =>
{
if (e.Error != null)
tcs.TrySetException(e.Error);
else if (e.Cancelled)
tcs.TrySetCanceled();
else
tcs.TrySetResult(e.Result);
};
wc.DownloadStringAsync(url);
return tcs.Task;
}

结合CancellationTokenSource实现超时任务

public static async Task<string> DownloadStringAsync(Uri url, TimeSpan timeout)
{
var tcs = new TaskCompletionSource<string>();
var wc = new WebClient();
wc.DownloadStringCompleted += (s, e) =>
{
if (e.Error != null)
tcs.TrySetException(e.Error);
else if (e.Cancelled)
tcs.TrySetCanceled();
else
tcs.TrySetResult(e.Result);
}; using var cts = new CancellationTokenSource();
cts.Token.Register(() => tcs.TrySetException(new TimeoutException()), useSynchronizationContext: false);
cts.CancelAfter(timeout); wc.DownloadStringAsync(url);
return await tcs.Task;
}

不足之处

一个实例只支持创建一次任务

一个TaskCompletionSource<>实例,给它的任务设置结果或异常之后,这个实例就没有什么用了,既无法重置,也无法再创建新的任务实例。在高密集创建TaskCompletionSource<>要求的场景里,这可能给GC带来一点压力。

没有原生支持延时设置异常或结果功能

在网络请求里或更多场景里,可能会收不到或在特定的时间内收不到响应事件,这时TaskCompletionSource<>不得不和CancellationTokenSource结合使用,加上计时器完成超时功能,又多得创建一个对象实例。

2 AwaitableCompletionSource介绍

AwaitableCompletionSource的灵感来源于asp.netcore的kestrel的SocketAwaitableEventArgs,它把SocketAsyncEventArgs改装成支持单例可重复await的功能。AwaitableCompletionSource也支持单例可重复await,同时使用过后不再使用的实例还支持dispose回收到池中。

  • 支持Singleton,单个实例持续使用;
  • 支持Dispose后回收复用,创建实例0分配;
  • 支持超时自动设置结果或异常,性能远好于TaskCompletionSource包装增加超时功能;

如何使用

使用方式与TaskCompletionSource大体一致。但是要使用静态类Create来创建实例,使用完成后Dispose实例。

var source = AwaitableCompletionSource.Create<string>();

ThreadPool.QueueUserWorkItem(s => ((IAwaitableCompletionSource)s).TrySetResult("1"), source);
Console.WriteLine(await source.Task); // 支持多次设置获取结果
source.TrySetResultAfter("2", TimeSpan.FromSeconds(1d));
Console.WriteLine(await source.Task); // 支持多次设置获取结果
source.TrySetResultAfter("3", TimeSpan.FromSeconds(2d));
Console.WriteLine(await source.Task); // 实例使用完成之后,可以进行回收复用
source.Dispose();

3 性能比较

瞬态实例和调用TrySetResult

在频繁创建与回收AwaitableCompletionSource的场景,对于SetResult的使用,AwaitableCompletionSource的cpu时间明显高于TaskCompletionSource,但内存分配为0。

Method Mean Error StdDev Gen 0 Gen 1 Gen 2 Allocated
TaskCompletionSource_SetResult 39.92 ns 0.201 ns 0.179 ns 0.0229 - - 96 B
AwaitableCompletionSource_SetResult 86.19 ns 0.315 ns 0.295 ns - - - -

单例和调用TrySetResult

单例AwaitableCompletionSource的场景,对于SetResult的使用,AwaitableCompletionSource与TaskCompletionSource的cpu时间相当,内存分配为0。

Method Mean Error StdDev Gen 0 Gen 1 Gen 2 Allocated
TaskCompletionSource_SetResult 41.46 ns 0.744 ns 1.180 ns 0.0229 - - 96 B
AwaitableCompletionSource_SetResult 49.30 ns 0.528 ns 0.494 ns - - - -

瞬态实例和超时等待

注: TaskCompletionSource<>结合CancellationTokenSource<>实现超时。

Method Mean Error StdDev Gen 0 Gen 1 Gen 2 Allocated
TaskCompletionSource_WithTimeout 237.0 ns 4.76 ns 5.85 ns 0.1357 - - 568 B
AwaitableCompletionSource_WithTimeout 176.6 ns 0.83 ns 0.74 ns - - - -

单例超时等待

注:AwaitableCompletionSource单例,TaskCompletionSource瞬态。

Method Mean Error StdDev Gen 0 Gen 1 Gen 2 Allocated
TaskCompletionSource_WithTimeout 233.1 ns 4.59 ns 6.58 ns 0.1357 - - 568 B
AwaitableCompletionSource_WithTimeout 131.5 ns 1.41 ns 1.32 ns - - - -

4 总结

AwaitableCompletionSource在多个场景下可替代TaskCompletionSource,项目我已开源在https://github.com/xljiulang/AwaitableCompletionSource

开源AwaitableCompletionSource,用于取代TaskCompletionSource的更多相关文章

  1. 我发起了一个 .Net Core 平台上的 分布式缓存 开源项目 ShareMemory 用于 取代 Redis

    Redis 的 安装 是 复杂 的, 使用 是 复杂 的, Redis 的 功能 是 重型 的, Redis 本身的 技术实现 是 复杂 的 . Redis 是用 C 写的, C 语言 编写的代码需要 ...

  2. PJNATH介绍 -- 开源的用于NAT穿透的ICE, STUN和TURN

    原文地址:http://blog.pjsip.org/2007/04/06/introducing-pjnath-open-source-ice-stun-and-turn/ ICE是什么? 对于那些 ...

  3. 开源 XFControls , 用于 Xamarin.Forms 的自定义控件集

    从此以后不会在博客园上发表任何言论,观注我的同志们,洗洗睡吧. ---------------------- 博文移至: http://www.jianshu.com/p/3ed1a3f10955

  4. IOS常用第三方开源类库&组件

    1.AFNetworking AFNetworking 采用 NSURLConnection + NSOperation, 主要方便与服务端 API 进行数据交换, 操作简单, 功能强大, 现在许多人 ...

  5. 网易新闻iOS版使用的18个开源组件

    转载来自:http://www.jianshu.com/p/8952944f7566  原文最后编辑时间:2015.05.19 网易新闻iOS版在开发过程中曾经使用过的第三方开源类库.组件 1.AFN ...

  6. iOS 常用开源代码整理

    本文章不定期整理. 1.AFNetworking AFNetworking 采用 NSURLConnection + NSOperation, 主要方便与服务端 API 进行数据交换, 操作简单, 功 ...

  7. 直接拿来用!Facebook移动开源项目大合集

    直接拿来用!Facebook移动开源项目大合集 时间:2014-04-22 15:37 作者:唐小引 随着iOS依赖管理工具CocoaPods和大量第三方开源库成熟起来,业界积累了大量的优秀开源项目. ...

  8. apache基金会开源项目简介

    apache基金会开源项目简介   项目名称 描述 HTTP Server 互联网上首屈一指的HTTP服务器 Abdera Apache  Abdera项目的目标是建立一个功能完备,高效能的IETF ...

  9. ios很好的开源库

    Tim9Liu9/TimLiu-iOS 自己总结的iOS.mac开源项目及库,持续更新.. 目录 UI 下拉刷新 模糊效果 AutoLayout 富文本 图表 表相关与Tabbar 隐藏与显示 HUD ...

随机推荐

  1. Known快速开发框架

    Known是一个基于.NET开发的快速开发框架,前后端分离,使用极少的第三方组件,开发简单快速,大部分代码可通过代码生成工具自动生成,非常适合单兵作战和小团队开发.前端UI是一个基于JQuery开发的 ...

  2. 用Python写个开心消消乐小游戏

    本文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,如有问题请及时联系我们以作处理 提到开心消消乐这款小游戏,相信大家都不陌生,其曾在 2015 年获得过玩家最喜爱的移动单机游戏奖,受 ...

  3. Swift3.0学习之基础部分

    1.常量和变量 常量和变量把一个名字(比如 maximumNumberOfLoginAttempts 或者 welcomeMessage )和一个指定类型的值(比如数字 10 或者字符串 " ...

  4. Core3.0使用Swagger接口文档

    前言 此方法为百度搜索结果,原文链接找不到了 步骤 1.引用Nuget Swashbuckle.AspNetCore 2.Startup.cs配置 //注册swagger服务,定义1个或者多个swag ...

  5. [UWP] - 修改应用程序在任务栏上的显示Logo

    用VS2015在windows 10上开发一个UWP的应用,由于windows 10对store应用进行了窗口化,因此可以看到在任务栏上看到应用程序的图标,但是看起来会感觉应用Logo会被嵌在另一个容 ...

  6. 【基础】:Rsync数据同步工具

    第二十一节 Rsync数据同步工具 1.1 Rsync介绍 1.1.1 什么是Rsync? 1.1.2 Rsync简介 1.3 Rsync的特性 1.1.4 Rsync的企业工作场景说明 1.2 Rs ...

  7. 工作中用的sql

    //字段是空字符串或者null select * from blade_process_should_pay_invoice where is_deleted = 0 and process_inst ...

  8. 【分布式锁】Redis实现可重入的分布式锁

    一.前言 之前写的一篇文章<细说分布式锁>介绍了分布式锁的三种实现方式,但是Redis实现分布式锁关于Lua脚本实现.自定义分布式锁注解以及需要注意的问题都没描述.本文就是详细说明如何利用 ...

  9. webservcie学习之webservice平台技术与开发

    webservice平台技术有哪些 XML+XSD,SOAP和WSDL就是构成WebService平台的三大技术. 1.XML+XSD WebService采用HTTP协议传输数据,采用XML格式封装 ...

  10. EF Core CodeFirst数据库自动迁移

    开发过程中都会遇到数据库数据结构更新的问题,怎么对数据库更新进行版本控制呢? 不同的项目对数据库版本更新控制的方式不同,常用的有第三方Evolve,开发人员将数据库更新脚本按照版本号的放在一起,然后执 ...