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

多线程,AsyncTaskMethodBuilder,异步,那些事 · 浏览次数 : 565

小编点评

**代码摘要** 该程序介绍了自定义异步生成器和异步方法构建器的使用,并展示了如何将它们与异步状态机结合使用以实现自定义异步生成器。 **主要功能** * 定义了一个名为 `MyTask` 的异步方法,该方法包含一个 `Task` 属性,用于存储异步操作的结果。 * 定义了一个名为 `CustomAwaiter` 的异步状态机,该状态机用于管理异步操作的执行状态。 * 在 `MyTask` 中,定义了一个 `GetAwaiter` 方法,该方法返回一个 `CustomAwaiter`实例,该实例用于异步操作的执行状态管理。 * 在 `CustomAwaiter` 中,定义了 `IsCompleted` 属性,用于标记异步操作是否完成。 * 在 `CustomAwaiter` 的 `OnCompleted` 方法中,设置了异步操作的状态机为完成状态。 * 在 `MyTask` 中,定义了一个 `AwaitOnCompleted` 方法,该方法用于异步等待 `CustomAwaiter` 完成异步操作。 **代码示例** ```csharp using System.Threading.Tasks; public class MyTaskBuilder { private readonly AsyncTaskMethodBuilder _builder; private T _value; public MyTaskBuilder() { _builder = new AsyncTaskMethodBuilder(); } public void Start(ref TStateMachine stateMachine) { _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 T Task { get { return _builder.Task; } } } ``` **自定义异步状态机** ```csharp using System.Threading.Tasks; public class CustomAsyncStateMechine : IAsyncStateMachine { private readonly MyTaskBuilder _builder; public CustomAsyncStateMechine() { _builder = new MyTaskBuilder(); } public void MoveNext() { throw new NotImplementedException(); } public void SetStateMachine(IAsyncStateMachine stateMachine) { throw new NotImplementedException(); } } ```

正文

引言    

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

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

引言 之前在上一篇文章中多线程合集(二) 异步的那些事,async和await原理抛析,我们从源码去分析了async和await如何运行,以及将编译后的IL代码写成了c#代码,以及实现自定义的Awaiter,自定义异步状态机同时将本系列的第一篇文章的自定义TaskScheduler和自定义的Awai

关系型数据库设计三大范式

作者:郑龙飞 范式定义 百度百科:设计关系数据库时,遵从不同的规范要求,设计出合理的关系型数据库,这些不同的规范要求被称为不同的范式,各种范式呈递次规范,越高的范式数据库冗余越小。 人类语言: 范式可以理解为设计一张数据表的表结构,符合的标准级别、规范和要求。 而通常我们用的最多的就是第一范式(1N

[转帖]kubernetes 证书合集

https://cloud.tencent.com/developer/article/2020655?areaSource=&traceId= 文章目录 PKI 证书 一共有多少证书? 为什么同一个“套”内的证书必须是同一个CA签署的? TLS bootstrapping kubelet证书为何不

算法学习笔记(8.2): 上下界网络流

# 上下界网络流 [TOC] > 前置知识以及更多芝士参考下述链接 > 网络流合集链接:[网络流](https://www.cnblogs.com/jeefy/p/17050215.html) 上下界网络流是普通网络流的一种变体,对于网络流,我们不仅关注其流量的上界,下届同样有所体现。 题型大致有五

OPPO 后端开发 一、二面面经

你好,我是 Guide,看了这么多面试成功的经验分享,今天来看一个读者分享的 Oppo 秋招面试失败经历。 面经合集请看:Java面试题&面经精选集。 下面是正文(文中的我为读者本人)。 个人情况 我的学校可能比大部分同学都比较差,是一个很一般的二本,土木专业转的计算机专业。 大三之前一直在做 C

Python提取文本文件(.txt)数据的方法

本文介绍基于Python语言,遍历文件夹并从中找到文件名称符合我们需求的多个.txt格式文本文件,并从上述每一个文本文件中,找到我们需要的指定数据,最后得到所有文本文件中我们需要的数据的合集的方法~

一键自动化博客发布工具,用过的人都说好(cnblogs篇)

cnblogs和其他的博客平台相比会比较复杂,需要设置的项目也比较多一些,弄懂了cnblogs的实现方式,那么你应该对selenium的整个框架使用已经烂熟于心了。 除了正常的标题,内容,摘要之外,cnblogs还需要设置个人分类,合集,投稿选项,投稿至网站分类,tags标签等内容。 要填的东西比较

LLaMA 3 源码解读-大语言模型5

title: llama3源码解读 tags: DL 本来不是很想写这一篇,因为网上的文章真的烂大街了,我写的真的很有可能没别人写得好。但是想了想,创建这个博客就是想通过对外输出知识的方式来提高自身水平,而不是说我每篇都能写得有多好多好然后吸引别人来看。那作为对整个合集内容的完善,这篇博客会解析现在

用ngrok实现内网穿透,一行命令就搞定!

最近在写支付的东西,调试时候需要让支付平台能够回调本地接口来更新支付成功的状态。但由于开发机器没有公网IP,所以需要使用内网穿透来让支付平台能够成功访问到本地开发机器,这样才能更高效率的进行调试。 推荐内网穿透的文章已经很多很多,还有很多大合集的推荐,但也因为推荐的太多,也会让人眼花缭乱,不断尝试不

Java多线程-ThreadPool线程池-3(五)

除了可以通过ThreadPoolExecutor自定义线程池外,同Stream API中的Collectors一样,多线程里的Executors类也提供了一组相关的线程池工具,可以直接拿来用,不用考虑用什么队列合适的问题。 Javac除了传统的四大线程池工具: 1、newFixedThreadPoo