多线程合集(三)---异步的那些事之自定义AsyncTaskMethodBuilder

这篇具有很好参考价值的文章主要介绍了多线程合集(三)---异步的那些事之自定义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;

 文章来源地址https://www.toymoban.com/news/detail-458409.html

        多线程合集(三)---异步的那些事之自定义AsyncTaskMethodBuilder

结束

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

 

到了这里,关于多线程合集(三)---异步的那些事之自定义AsyncTaskMethodBuilder的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • PCIE那些事之linux下EP驱动实现方式二

    EP设备驱动,主要运行在RC侧,用于控制总线地址上的数据传输使用, 提供给应用层接口,应用层调用此接口完成数据传输,主要的分层结构如下 RC侧包含RC控制器驱动 和EP设备驱动 EP侧包含EP控制器驱动和EP端口驱动 (无需关心,一般厂商提供) 实现的主要是EP设备驱动 主要分

    2023年04月08日
    浏览(28)
  • Spring Boot使用@Async实现异步调用:自定义线程池

    第一步,先在Spring Boot主类中定义一个线程池,比如: 上面我们通过使用​​ ThreadPoolTaskExecutor ​​创建了一个线程池,同时设置了以下这些参数: 核心线程数10:线程池创建时候初始化的线程数 最大线程数20:线程池最大的线程数,只有在缓冲队列满了之后才会申请超过核

    2024年02月14日
    浏览(49)
  • 训练yolov5的那些事之解决:AssertionError: Label class x exceeds nc=x in data/yolov5.yaml. Possible class label

    Yolov5报错: AssertionError: Label class x exceeds nc=x in data/yolov5.yaml. Possible class labels are 0-x-1 File “C:Users1Desktop水表识别YOLO5yolov5-mastertrain.py”, line 175, in train assert mlc nc, ‘Label class %g exceeds nc=%g in %s. Possible class labels are 0-%g’ % (mlc, nc, opt.data, nc - 1) 找到train文件的175行: 改成这样

    2024年02月11日
    浏览(56)
  • SpringMVC之自定义注解

    目录 前言 一、自定义注解 1.Java注解简介 2. 注解的用处 3. 为什么要用注解 4.自定义注解的应用场景 5. 注解的分类 6.如何定义并使用自定义注解 7.自定义注解三种使用案例 案例一: 案例二: 案例三: 二、Aop自定义注解的应用   1 .自定义注解类 2.切面类 3.Controller层 随着We

    2024年02月07日
    浏览(50)
  • SpringBoot之自定义starter

    目录 一、什么是SpringBoot starter机制 二、为什么要自定义starter 三、什么时候需要创建自定义starter 四、自动加载核心注解说明 五、自定义starter的开发流程 案例一:为短信发送功能创建一个starter 案例二:AOP方式统一服务日志 SpringBoot中的starter是一种非常重要的机制(自动化配

    2024年02月01日
    浏览(37)
  • Android 之自定义绘制一

    绘制的基本要素 onDraw(Canvas) 绘制方法 Canvas 绘制工具 Paint 调整风格 粗细等 坐标系: x y ,3D 会有z轴,x  左到右,y 上至下,与数学中y颠倒 尺寸单位: 布局中 dp ,sp ,代码中 px;dp 为了适配不同的尺寸 绘制的关键: draw(Canvas )......(关键类:Paint) Paint.ANTI_ALIAS_FLAG 抗锯齿 paint.setFlag 像

    2024年02月11日
    浏览(48)
  • react之自定义hooks

    原文合集地址如下,有需要的朋友可以关注 本文地址 合集地址 任何相对独立、复用性强的逻辑,都可以 extract 为自定义 Hook,自定义 Hook 是一种复用 React 的状态逻辑的函数。 自定义 Hook 的主要特点是: 抽象组件间的状态逻辑,方便复用 让功能组件更纯粹,更易于维护 自定义

    2024年02月12日
    浏览(43)
  • Flutter之自定义路由切换动画

    在Flutter中,我们可以通过Navigator来实现路由管理,包括路由的跳转和返回等。默认情况下,Flutter提供了一些简单的路由切换动画,但是有时候我们需要自定义一些特殊的动画效果来提高用户体验。本文将介绍如何在Flutter中实现自定义的路由切换动画。 在Flutter中,路由切换

    2024年02月10日
    浏览(37)
  • C#(三十一)之自定义事件

    自定义事件:一定要注意下面六部曲 1:声明关于事件的委托 2:声明事件 3:编写触发事件的函数 4:创建事件处理程序 5:注册事件处理程序 6:触发事件 定义事件: 声明事件时event可以省略(最好不要省略) 事件继承 事件event都是继承自EventArgs,通过继承EventArgs可以给自

    2024年02月13日
    浏览(43)
  • Angular系列教程之自定义指令

    在Angular中,指令是一种非常强大的工具,用于扩展HTML元素的功能和行为。它们允许我们创建可重用的组件,并在应用程序中的多个地方使用它们。本文将介绍Angular指令的基础知识,并附上示例代码进行解释说明。 指令是Angular应用程序的构建块之一。它们通过@Directive装饰器

    2024年01月17日
    浏览(37)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包