多线程合集(三)---异步的那些事之自定义AsyncTaskMethodBuilder
引言
之前在上一篇文章中多线程合集(二)---异步的那些事,async和await原理抛析,我们从源码去分析了async和await如何运行,以及将编译后的IL代码写成了c#代码,以及实现自定义的Awaiter,自定义异步状态机同时将本系列的第一篇文章的自定义TaskScheduler和自定义的Awaiter结合起来,将代码跑了起来,而在c#10之后,我们可以实现自定义的异步生成器,在上一篇文章中,我们将编译后的代码还原成了c#代码,其中就有用到了一个AsyncTaskMethodBuilder的类,搁以前我们只能使用编译器编译之后的AsyncTaskMethodBuilder,现在我们已经可以自定义了,如果再加上上一章节的自定义状态机,加调度,可能会更好玩一些,接下来就为大家奉上代码。
代码
总共没有多少代码,只是为了简单的实现自定义的AsyncTaskMethodBuilder, 当然可能后续某位哥哥会用到将这些知识点串联起来使用呢,可以看到,下面我们继承了Task,实现了MyTask,此处演示效果,仅仅实现了一个构造函数以及一个GetAwaiter的方法,然后上面就是我们测试调用的Test方法,为什么还需要new一个新的GetAwaiter呢,如果我们使用默认的TaskAwaiter,那你在Main方法await tes.Test的时候就会卡死的至于原因,就是await之后的代码等待结果是等待await之后的返回到上一层也就是说await后面的主动推结果,但是卡死是因为上一层却主动找我要结果导致的卡死,导致我推不过去,上一层也找不到结果,此处我没有具体分析,但是我的猜测是这样,看官们可以自己尝试一下,将MyTask的GetAwaiter注释,使用默认的TaskAwaiter,然后调用Test方法,如果是await的时候肯定卡死,但是如果Task同步运行,也就是RunSynchronously这种方式运行,然后直接.Result,就可以获取到结果,刚好可以验证我上面的猜测,同一上下文了,不需要他主动推,但我可以主动获取,
然后在往下面走就是我们自定义的一个Awaiter,实现接口后,构造函数的Func是我们返回结果的委托,这个结果是GetResult之后的结果值,OnCompleted方法和下面的Unsafe都是去推进状态机告诉已经完了异步的,上一章节说过这两个方法的参数Action,实际上就是状态机的MoveNext方法,最后就到了我们的自定义Builder实现,只需要遵循如下条件,官网列出的条件,既可以实现一个自定义的Builder,
// See https://aka.ms/new-console-template for more information
using System.Reflection.PortableExecutable;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
public class Program
{
static async Task Main(string[] args)
{ var tes = new TestAsync();
var task =await tes.Test();
Console.ReadKey();
}
}
public class TestAsync
{
public async MyTask<int> Test()
{
await MyTask<int>.Delay(1);
return 100;
}
} [AsyncMethodBuilder(typeof(MyTaskBuilder<>))]
public class MyTask<T> : Task<T> where T : notnull
{
public MyTask(Func<T> action) : base(action)
{
Action = action;
} public Task<T> Task { get; }
public Func<T> Action { get; } //
// 摘要:
// Gets an awaiter used to await this System.Threading.Tasks.Task`1.
//
// 返回结果:
// An awaiter instance.
public new CustomAwaiter<T> GetAwaiter()
{
var awaiter=new CustomAwaiter<T>(Action);
return awaiter;
} // 添加构造函数和其他功能代码
}
public class CustomAwaiter<T> : ICriticalNotifyCompletion
{
public CustomAwaiter(Func<T> func)
{
Func = func;
}
public bool IsCompleted { get; set; }
public Func<T> Func { get; } public void OnCompleted(Action continuation)
{
continuation();
IsCompleted = true;
} public void UnsafeOnCompleted(Action continuation)
{
continuation();
IsCompleted = true;
}
public T GetResult()
{
return Func() ;
}
} public class MyTaskBuilder<T> where T:notnull
{
private readonly AsyncTaskMethodBuilder<T> _builder = new AsyncTaskMethodBuilder<T>();
private T Value;
public static MyTaskBuilder<T> Create()
{
return new MyTaskBuilder<T>();
} public void Start<TStateMachine>(ref TStateMachine stateMachine) where TStateMachine : IAsyncStateMachine
{
_builder.Start(ref stateMachine);
} public void SetStateMachine(IAsyncStateMachine stateMachine)
{
_builder.SetStateMachine(stateMachine);
} public void SetResult(T val)
{
Value = val;
_builder.SetResult(val);
} public void SetException(Exception exception)
{
_builder.SetException(exception);
}
public MyTask<T> Task
{
get
{
return new MyTask<T>(new Func<T>(() => Value));
}
} public void AwaitOnCompleted<TAwaiter, TStateMachine>(ref TAwaiter awaiter, ref TStateMachine stateMachine)
where TAwaiter : INotifyCompletion
where TStateMachine : IAsyncStateMachine
{
_builder.AwaitOnCompleted(ref awaiter, ref stateMachine);
} public void AwaitUnsafeOnCompleted<TAwaiter, TStateMachine>(ref TAwaiter awaiter, ref TStateMachine stateMachine)
where TAwaiter : ICriticalNotifyCompletion
where TStateMachine : IAsyncStateMachine
{
_builder.AwaitUnsafeOnCompleted(ref awaiter, ref stateMachine);
}
}
public class StateMachine : IAsyncStateMachine
{
public StateMachine()
{ }
public void MoveNext()
{
throw new NotImplementedException();
} public void SetStateMachine(IAsyncStateMachine stateMachine)
{
throw new NotImplementedException();
}
}
自定义Builder的条件
自定义AsyncTaskMethodBuilder,需要满足一下条件,即你定义的这个Builder类需要有Create方法,Task的属性,SetException,设置异常的,SetResult设置结果的,以及一个Start的方法,同时在需要指定异步Builder的类或者方法使用AsyncMethodBuilderArrtibute特性,里面需要的参数就是你自定义Builder的type,即要么在MyTask类上面使用此特性,也可以直接在Test方法上面添加此特性都可以实现自定义Builder,当然了此处有个扩展就是你可以参考上一章节的自定义状态机,调度器,awaiter,自己手动实现编译器编译之后的代码,也就是下面这一段,当然了,内功深厚自己借此实现一个简单的异步也是没问题的,自己实现Task,类似我如上,继承Task,然后借助线程上下文等一些api,去实现一个自己的异步也不是什么难得事情,总之,此片文章实际上可能业务中会用不到,但是结合前几篇,也可以更好的理解async和await了。
CustomAsyncStateMechine customAsyncStateMechine = new CustomAsyncStateMechine();
customAsyncStateMechine.builder = AsyncTaskMethodBuilder<string>.Create();
customAsyncStateMechine.State = -1;
customAsyncStateMechine.builder.Start(ref customAsyncStateMechine);
return customAsyncStateMechine.builder.Task;

结束
今天水的一篇博客就到这里了,因为大家能更好的理解async和await,能够将这些自定义的东西玩出花来,哈哈,关于async和await以及线程方面,感兴趣的可以看看我之前的文章。
多线程合集(三)---异步的那些事之自定义AsyncTaskMethodBuilder的更多相关文章
- 多线程合集(二)---异步的那些事,async和await原理抛析
引言 在c#中,异步的async和await原理,以及运行机制,可以说是老生常谈,经常在各个群里看到有在讨论这个的,而且网上看到的也只是对异步状态机的一些讲解,甚至很多人说异步状态机的时候,他们说的是 ...
- 多线程合集(一)---信号量,锁,以及并发编程,自定义任务调度和awaiter
引言 在后端开发中,多线程技术总是后端开发中常用到的技术,那什么是多线程呢,在操作系统中,程序运行的最小单位是进程,那线程则是进程里面的最小单位,关系是一对多的关系,而线程的调度,是由操作系统的时间片 ...
- IL合集
由于之前写的表达式树合集,未编写任何注释且是以图片的形式展现给大家,在这里向各位看官道歉了,接下来为大家奉上新鲜出炉的香喷喷的IL合集,后面会持续更新,各位看官点关注不迷路,之前答应的手写IOC以及多 ...
- 备战金三银四!一线互联网公司java岗面试题整理:Java基础+多线程+集合+JVM合集!
前言 回首来看2020年,真的是印象中过的最快的一年了,真的是时间过的飞快,还没反应过来年就夸完了,相信大家也已经开始上班了!俗话说新年新气象,马上就要到了一年之中最重要的金三银四,之前一直有粉丝要求 ...
- 【收藏】Java多线程/并发编程大合集
(一).[Java并发编程]并发编程大合集-兰亭风雨 [Java并发编程]实现多线程的两种方法 [Java并发编程]线程的中断 [Java并发编程]正确挂起.恢复.终止线程 [ ...
- JS基础笔记合集(1-3)
JavaScript合集 1. JS入门基础 2. JS数据类型 3. JS运算符 4. JS流程控制 5. JS对象 6. JS函数 7. JS面向对象 8. JS数组 9. JS内置对象 我追求理 ...
- 掘金 Android 文章精选合集
掘金 Android 文章精选合集 掘金官方 关注 2017.07.10 16:42* 字数 175276 阅读 50053评论 13喜欢 669 用两张图告诉你,为什么你的 App 会卡顿? - A ...
- 【死磕Java并发】----- 死磕 Java 并发精品合集
[死磕 Java 并发]系列是 LZ 在 2017 年写的第一个死磕系列,一直没有做一个合集,这篇博客则是将整个系列做一个概览. 先来一个总览图: [高清图,请关注"Java技术驿站&quo ...
- WhyEngine游戏合集2014贺岁版
WhyEngine游戏合集2014贺岁版 自去年9月份开始写我的第一个小游戏,到现在为止,共实现了14个小游戏,10个屏保程序,7个DEMO程序.开发环境是VS2008,渲染使用的是D3D,所有代码都 ...
- SAP成都研究院2018年总共87篇技术文章合集
2018年很快就要结束了.Jerry在2017年年底准备开始写这个公众号时,给自己定的目标是:2018年至少保证每周发布一篇高质量的文章.如今2018年就快过去了,高质量与否需要大家来反馈,至少从量上 ...
随机推荐
- python代码换行问题(用‘\’来达成)
在 Python 中,可以使用反斜杠符号 '\' 来表示代码换行,从而实现在代码中进行换行,并保持语句的完整性.例如:. # 使用反斜杠符号进行换行 result = 10 + \ 20 + \ 30 ...
- SqlServer 高并发的情况下,如何利用锁保证数据的稳定性
sql的锁机制,是时刻贯彻在每一次的sql事务中的,为了理解更透彻,介绍锁之前,我们得先了解,锁是为了干什么!! 1.数据库异常情况 1.1 先来聊聊数据可能发生个异常状况 1)脏读:读未提交,顾名思 ...
- NGINX配置SSL支持
前言 在文章-腾讯云申请免费SSL证书中, 我们已经申请好了SSL证书. 那么现在, 我们就要配置全站SSL了! 这次的工作主要是NGINX的配置, 同时会有一些我的博客本身的配置. 博客本身配置更改 ...
- [C++/Java/Py/C#/Ruby/Swift/Go/Scala/Kotlin/Rust/PHP/TS/Elixir/Dart/Racket/Erlang] LeetCode2185. 统计包含给定前缀的字符串
目录 题解地址 代码 cpp java python3 C# ruby swift golang scala kotlin rust php typescript elixir dart racket ...
- MATLAB信号处理常用函数(转载)
https://shimo.im/docs/YyRXY8cQdqY8RJvc/ <MATLAB信号处理工具箱>,可复制链接后用石墨文档 App 或小程序打开 嗯这个肯定是随便看看,有个印象 ...
- 能让Java开发者提高效率的10个工具
Java受到全球百万计开发者的追捧,已经演变为一门出色的编程语言.最终,这门语言随着技术的变化,不断的被改善以迎合变化的市场需求. 无论你是否拥有一家科技公司,软件已经成为几乎每一个企业不可或缺的 ...
- MyBatisPlus 实战字典
MyBatis-Plus(简称 MP)是一个 MyBatis 的增强工具包,只做增强不做改变,为简化开发工作.提高生产效率而生. 一.Service CRUD 接口 [说明]:[1]通用 Servic ...
- [Java EE]解决浏览器跨域问题
1 解决浏览器跨域问题的方案 方式1: 浏览器(chrome)中取消跨域限制 step1 浏览器 chrome://flags step2 搜索:same step3 将搜索结果中的3个插件[Same ...
- vim使用教程(最简单最全面的教程)
本教程是vimtutor的原版内容.这是我读过最简单最全面的vim教程. 偶仅仅是优秀内容的搬运工,放在此处便于查阅,方便学习,版权归原作者所有. 注意:每一节的命令操作将会更改本文.推荐您复制本文的 ...
- 关键字——static
static 关键字具有共享属性,放在方法区中