经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 程序设计 » 编程经验 » 查看文章
多线程合集(三)---异步的那些事之自定义AsyncTaskMethodBuilder
来源:cnblogs  作者:四处观察  时间:2023/5/26 9:56:16  对本文有异议

引言    

    之前在上一篇文章中多线程合集(二)---异步的那些事,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,

  1. // See https://aka.ms/new-console-template for more information
  2. using System.Reflection.PortableExecutable;
  3. using System.Runtime.CompilerServices;
  4. using System.Threading.Tasks;
  5. public class Program
  6. {
  7. static async Task Main(string[] args)
  8. {
  9. var tes = new TestAsync();
  10. var task =await tes.Test();
  11. Console.ReadKey();
  12. }
  13. }
  14. public class TestAsync
  15. {
  16. public async MyTask<int> Test()
  17. {
  18. await MyTask<int>.Delay(1);
  19. return 100;
  20. }
  21. }
  22. [AsyncMethodBuilder(typeof(MyTaskBuilder<>))]
  23. public class MyTask<T> : Task<T> where T : notnull
  24. {
  25. public MyTask(Func<T> action) : base(action)
  26. {
  27. Action = action;
  28. }
  29. public Task<T> Task { get; }
  30. public Func<T> Action { get; }
  31. //
  32. // 摘要:
  33. // Gets an awaiter used to await this System.Threading.Tasks.Task`1.
  34. //
  35. // 返回结果:
  36. // An awaiter instance.
  37. public new CustomAwaiter<T> GetAwaiter()
  38. {
  39. var awaiter=new CustomAwaiter<T>(Action);
  40. return awaiter;
  41. }
  42. // 添加构造函数和其他功能代码
  43. }
  44. public class CustomAwaiter<T> : ICriticalNotifyCompletion
  45. {
  46. public CustomAwaiter(Func<T> func)
  47. {
  48. Func = func;
  49. }
  50. public bool IsCompleted { get; set; }
  51. public Func<T> Func { get; }
  52. public void OnCompleted(Action continuation)
  53. {
  54. continuation();
  55. IsCompleted = true;
  56. }
  57. public void UnsafeOnCompleted(Action continuation)
  58. {
  59. continuation();
  60. IsCompleted = true;
  61. }
  62. public T GetResult()
  63. {
  64. return Func() ;
  65. }
  66. }
  67. public class MyTaskBuilder<T> where T:notnull
  68. {
  69. private readonly AsyncTaskMethodBuilder<T> _builder = new AsyncTaskMethodBuilder<T>();
  70. private T Value;
  71. public static MyTaskBuilder<T> Create()
  72. {
  73. return new MyTaskBuilder<T>();
  74. }
  75. public void Start<TStateMachine>(ref TStateMachine stateMachine) where TStateMachine : IAsyncStateMachine
  76. {
  77. _builder.Start(ref stateMachine);
  78. }
  79. public void SetStateMachine(IAsyncStateMachine stateMachine)
  80. {
  81. _builder.SetStateMachine(stateMachine);
  82. }
  83. public void SetResult(T val)
  84. {
  85. Value = val;
  86. _builder.SetResult(val);
  87. }
  88. public void SetException(Exception exception)
  89. {
  90. _builder.SetException(exception);
  91. }
  92. public MyTask<T> Task
  93. {
  94. get
  95. {
  96. return new MyTask<T>(new Func<T>(() => Value));
  97. }
  98. }
  99. public void AwaitOnCompleted<TAwaiter, TStateMachine>(ref TAwaiter awaiter, ref TStateMachine stateMachine)
  100. where TAwaiter : INotifyCompletion
  101. where TStateMachine : IAsyncStateMachine
  102. {
  103. _builder.AwaitOnCompleted(ref awaiter, ref stateMachine);
  104. }
  105. public void AwaitUnsafeOnCompleted<TAwaiter, TStateMachine>(ref TAwaiter awaiter, ref TStateMachine stateMachine)
  106. where TAwaiter : ICriticalNotifyCompletion
  107. where TStateMachine : IAsyncStateMachine
  108. {
  109. _builder.AwaitUnsafeOnCompleted(ref awaiter, ref stateMachine);
  110. }
  111. }
  112. public class StateMachine : IAsyncStateMachine
  113. {
  114. public StateMachine()
  115. {
  116. }
  117. public void MoveNext()
  118. {
  119. throw new NotImplementedException();
  120. }
  121. public void SetStateMachine(IAsyncStateMachine stateMachine)
  122. {
  123. throw new NotImplementedException();
  124. }
  125. }

自定义Builder的条件

    自定义AsyncTaskMethodBuilder,需要满足一下条件,即你定义的这个Builder类需要有Create方法,Task的属性,SetException,设置异常的,SetResult设置结果的,以及一个Start的方法,同时在需要指定异步Builder的类或者方法使用AsyncMethodBuilderArrtibute特性,里面需要的参数就是你自定义Builder的type,即要么在MyTask类上面使用此特性,也可以直接在Test方法上面添加此特性都可以实现自定义Builder,当然了此处有个扩展就是你可以参考上一章节的自定义状态机,调度器,awaiter,自己手动实现编译器编译之后的代码,也就是下面这一段,当然了,内功深厚自己借此实现一个简单的异步也是没问题的,自己实现Task,类似我如上,继承Task,然后借助线程上下文等一些api,去实现一个自己的异步也不是什么难得事情,总之,此片文章实际上可能业务中会用不到,但是结合前几篇,也可以更好的理解async和await了。

  1. CustomAsyncStateMechine customAsyncStateMechine = new CustomAsyncStateMechine();
  2. customAsyncStateMechine.builder = AsyncTaskMethodBuilder<string>.Create();
  3. customAsyncStateMechine.State = -1;
  4. customAsyncStateMechine.builder.Start(ref customAsyncStateMechine);
  5. return customAsyncStateMechine.builder.Task;

 

        

结束

    今天水的一篇博客就到这里了,因为大家能更好的理解async和await,能够将这些自定义的东西玩出花来,哈哈,关于async和await以及线程方面,感兴趣的可以看看我之前的文章。

 

原文链接:https://www.cnblogs.com/1996-Chinese-Chen/p/17428596.html

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号