async&await的前世今生

microex microex     2022-10-12     551

关键词:

async&await=custom IAsyncStateMachine
async&await是IAsyncStateMachine的语法糖

验证

分别使用async&await和IAsyncStateMachine遍历一棵树,查看二者的线程id和线程上下文标识是否相同

数据结构

public class Node
{
    private static List<Node> _nodes = new List<Node>();
    private static int _id = 1;
    public Node()
    {
        this.Id = _id++;
        _nodes.Add(this);
    }

    public int Id { get; }

    public Node Left { get; set; }
    public Node Right { get; set; }

    public bool IsLeaf => this.Left == null && this.Right == null;
    public bool IsTraveled { get; set; } = false;

    public override string ToString()
    {
        return $"{Left?.Id ?? 0}|{this.Id}|{Right?.Id ?? 0}";
    }
}

使用async&await遍历树

public static async Task<int> Travle(Node node)
{
    node.IsTraveled = true;
    if (!node.IsLeaf)
    {
        Console.WriteLine("线程id:" + Thread.CurrentThread.ManagedThreadId + "|线程上下文标识:" + Thread.CurrentThread.ExecutionContext.GetHashCode() + ":" + await Travle(node.Left));
        Console.WriteLine("线程id:" + Thread.CurrentThread.ManagedThreadId + "|线程上下文标识:" + Thread.CurrentThread.ExecutionContext.GetHashCode() + ":" + await Travle(node.Right));
    }
    return node.Id;
}

使用IAsyncStateMachine遍历树

public static Task<int> StateMechineTravle(Node node)
{
    StateMechine stateMechine = new StateMechine();
    stateMechine.node = node;
    stateMechine.builder = AsyncTaskMethodBuilder<int>.Create();
    stateMechine.state = -1;
    AsyncTaskMethodBuilder<int> next_builder = stateMechine.builder;
    next_builder.Start<StateMechine>(ref stateMechine);
    return stateMechine.builder.Task;
}

这里StateMechine是实现IAsyncStateMachine接口的一个类

public struct StateMechine : IAsyncStateMachine
{
    public int state;

    public AsyncTaskMethodBuilder<int> builder;

    public Node node;

    private object wrap1;

    private object wrap2;

    private TaskAwaiter<int> awaiter;

    void IAsyncStateMachine.MoveNext()
    {
        int num = this.state;
        int id;
        try
        {
            TaskAwaiter<int> taskAwaiter;
            if (num != 0)
            {
                if (num == 1)
                {
                    taskAwaiter = this.awaiter;
                    this.awaiter = default(TaskAwaiter<int>);
                    this.state = -1;
                    goto IL_1AB;
                }
                this.node.IsTraveled = true;
                if (this.node.IsLeaf)
                {
                    goto IL_20C;
                }
                this.wrap1 = Thread.CurrentThread.ManagedThreadId;
                this.wrap2 = Thread.CurrentThread.ExecutionContext.GetHashCode();
                taskAwaiter = Program.StateMechineTravle(this.node.Left).GetAwaiter();
                if (!taskAwaiter.IsCompleted)
                {
                    this.state = 0;
                    this.awaiter = taskAwaiter;
                    this.builder.AwaitUnsafeOnCompleted<TaskAwaiter<int>, StateMechine>(ref taskAwaiter, ref this);
                    return;
                }
            }
            else
            {
                taskAwaiter = this.awaiter;
                this.awaiter = default(TaskAwaiter<int>);
                this.state = -1;
            }
            int arg_CC_0 = taskAwaiter.GetResult();
            taskAwaiter = default(TaskAwaiter<int>);
            object obj = arg_CC_0;
            Console.WriteLine(string.Concat(new object[]
            {
                "线程id:",
                this.wrap1,
                "|线程上下文标识:",
                this.wrap2,
                ":",
                obj
            }));
            this.wrap1 = null;
            this.wrap2 = null;
            this.wrap2 = Thread.CurrentThread.ManagedThreadId;
            this.wrap1 = Thread.CurrentThread.ExecutionContext.GetHashCode();
            taskAwaiter = Program.StateMechineTravle(this.node.Right).GetAwaiter();
            if (!taskAwaiter.IsCompleted)
            {
                this.state = 1;
                this.awaiter = taskAwaiter;
                this.builder.AwaitUnsafeOnCompleted<TaskAwaiter<int>, StateMechine>(ref taskAwaiter, ref this);
                return;
            }
            IL_1AB:
            int arg_1BA_0 = taskAwaiter.GetResult();
            taskAwaiter = default(TaskAwaiter<int>);
            obj = arg_1BA_0;
            Console.WriteLine(string.Concat(new object[]
            {
                "线程id:",
                this.wrap2,
                "|线程上下文标识:",
                this.wrap1,
                ":",
                obj
            }));
            this.wrap2 = null;
            this.wrap1 = null;
            IL_20C:
            id = this.node.Id;
        }
        catch (Exception exception)
        {
            this.state = -2;
            this.builder.SetException(exception);
            return;
        }
        this.state = -2;
        this.builder.SetResult(id);
    }

    [DebuggerHidden]
    void IAsyncStateMachine.SetStateMachine(IAsyncStateMachine stateMachine)
    {
        this.builder.SetStateMachine(stateMachine);
    }
}

结果

输入1,使用async&await遍历树
输入2,使用IAsyncStateMachine遍历树
可以看出,二者一毛一样
技术分享图片


技术分享图片

可见,基于async和await的task不会被多线程调用

示例代码

https://github.com/snys98/AsyncStateMechineTest

官方资料

https://docs.microsoft.com/zh-cn/dotnet/api/system.runtime.compilerservices.iasyncstatemachine?view=netframework-4.7.1






async&await异步请求处理办法(代码片段)

async&await异步请求处理办法目录async&await异步请求处理办法async&await一、async1、async函数2、回调async函数以获取结果二、await末async&awaitasync函数&await规定于ES2017.它们是基于promises的语法糖,使我们得以以更简洁的方式... 查看详情

lru算法的今生前世&lrucache在android中的实现(代码片段)

操作系统中的起源缓存文件置换机制现代语言的很多特性都可以在操作系统中找到最初的原型,LRU我们最早也可以在操作系统中找到当初的设计。“高速缓存是计算机科学中唯一重要的思想”-BillJoy我们知道,无论是内存... 查看详情

demo_09async&await

// async位于函数字面量或函数表达式的前面(普通函数,立即执行函数,箭头函数均可),被修饰函数的返回一个Promise对象// 简化Promise的使用过程,让你的异步代码看起来像是同步的/*await一定要位于async函数内部await一般位... 查看详情

多线程async&await

...取消等操作,可谓已经很强大了。但.net4.5为我们带来了async&await,使得实现多线程的写法更简单,更优美,更符合线性思维。下面通过一个例子来演示通过Task和async&await分别如何实现,并且最后还附上代码执行顺序图。使... 查看详情

html的前世今生

...                      HTML的前世今生                                                      作者:尹正杰版权声明:原创作品,谢... 查看详情

css的前世今生

...                       Css的前世今生                                                作者:尹正杰版权声明:原创作品,谢绝转载!否则... 查看详情

javascript的es6中async&&await的简单使用以及介绍(代码片段)

async&await是Promise和Generator的语法糖,使用他的目的就是用同步的写法,写异步的操作,去解决回调地狱async是“异步”的简写,async用于申明一个异步的functionawait可以认为是asyncwait的简写,await用于等待一个... 查看详情

Angular 1.5 && Async/Await && 茉莉花测试

】Angular1.5&&Async/Await&&茉莉花测试【英文标题】:Angular1.5&&Async/Await&&jasminetests【发布时间】:2017-04-2301:03:41【问题描述】:我已经到处找了,但还没有找到适合我的特殊情况的解决方案。我们使用Angular1.5... 查看详情

async&await

【await】  The await operatorisusedtowaitfora Promise.Itcanonlybeusedinside an asyncfunction.  Returnstheresolvedvalueofthepromise,orthevalueitselfifit‘snota Promise.  The& 查看详情

git前世今生

GIT前世今生GIT到底是什么Git是一款免费、开源的分布式版本控制系统,用于敏捷高效地处理任何或小或大的项目。命名的由来(仅供参考)Thename"git"wasgivenbyLinusTorvaldswhenhewrotetheveryfirstversion.Hedescribedthetoolas"thestupidcontenttracker"andthe... 查看详情

.netcore001.netcore前世今生

文章目录.NetCore前世今生C#的概述Asp.NetCoreMVC(应用框架).NetCore前世今生.Net5就是.NetCore5不能向后兼容C#的概述Asp.NetCoreMVC(应用框架)相当于SpringMVC,是.Net的应用框架 查看详情

async&await异步编程的一点巧方法

...it关键字不会创建新的线程,而是由Task任务或是FCL中的xxxAsync等方法创建的线程,而且这里创建的线程都是基于线程池创建的工作线程,属于后台线程。 await关键字会阻塞/暂停调用它的方法,也即下面的Phycology方法.当阻塞其... 查看详情

bert的前世今生

TransformerTransformer来自论文:?AllAttentionIsYouNeed别人的总结资源:谷歌官方AI博客:?Transformer:ANovelNeuralNetworkArchitectureforLanguageUnderstandingAttention机制详解(二)——Self-Attention与Transformer谷歌软件工程师放弃幻想,全面拥抱Transf 查看详情

如何使用 async/await 处理错误?

】如何使用async/await处理错误?【英文标题】:Howtohandleerrorsusingasync/await?【发布时间】:2018-09-0310:09:54【问题描述】:¿在nodeJS中使用async/await实现promise错误处理程序.catch((err)=&gt;)的最佳实践是什么?代码运行在nodeJSV8.10.0这... 查看详情

前端的“前世今生”

...决定入“前端坑”以来,到现在突然想了解一下前端的“前世今生”,看看她到底是如何修炼成神,被大家所崇拜并有无数人跟随的。我这个草根到15年的时候才了解到“大神”,真是相见恨晚啊!  我虽比“大神”早出生,... 查看详情

lambda表达式的前世今生~~~~~~

namespaceMyLamdba{classProgram{staticvoidMain(string[]args){LamDbaShow.Show();Console.ReadKey();}}}===================================================================================================== 查看详情

gc的前世与今生

...文地址:http://kb.cnblogs.com/page/106720/  作者:springyangGC的前世与今生  虽然本文是以.NET作为目标来讲述GC,但是GC的概念并非才诞生不久。早在1958年,由鼎鼎大名的图林奖得主JohnMcCarthy所实现的Lisp语言就已经提供了GC的功能,... 查看详情

javascript的前世今生

JavaScript特点:松散性:它的变量不必具有一个明确的类型对象属性:JavaScript中的对象把属性名映射为任意的属性值,它的这种方式很像哈希表或关联数组,而不像C中的结构体或者C++、Java中的对象。继承机制:JavaScript中的面向... 查看详情