精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

聊一聊 C# 異步任務延續的三種底層玩法

開發 前端
雖然異步任務延續?有三種實現方法,但底層都是一個套路,即借助 Task.m_continuationObject? 字段玩出的各種花樣,當然他們也是有一些區別的,即對 m_continuationObject 任務是否用單獨的線程調度,產生了不同的意見分歧。

一、背景

1. 講故事

最近聊了不少和異步相關的話題,有點疲倦了,今天再寫最后一篇作為近期這類話題的一個封筆吧,下篇繼續寫我熟悉的 生產故障 系列,突然親切感油然而生,哈哈,免費給別人看程序故障,是一種積陰德陽善的事情,欲知前世因,今生受者是。欲知來世果,今生做者是。

在任務延續方面,我個人的總結就是三類,分別為:

  1. StateMachine
  2. ContinueWith
  3. Awaiter

話不多說,我們逐個研究下底層是咋玩的?

二、異步任務延續的玩法

1. StateMachine

說到狀態機大家再熟悉不過了,也是 async,await 的底層化身,很多人看到 async await 就想到了IO場景,其實IO場景和狀態機是兩個獨立的東西,狀態機是一種設計模式,把這個模式套在IO場景會讓代碼更加絲滑,僅此而已。為了方便講述,我們寫一個 StateMachine 與 IO場景 無關的一段測試代碼。

internal class Program
    {
        static void Main(string[] args)
        {
            UseAwaitAsync();

            Console.ReadLine();
        }

        static async Task<string> UseAwaitAsync()
        {
            var html = await Task.Run(() =>
            {
                Thread.Sleep(1000);
                var response = "<html><h1>博客園</h1></html>";
                return response;
            });
            Console.WriteLine($"GetStringAsync 的結果:{html}");
            return html;
        }
    }

那這段代碼在底層是如何運作的呢?剛才也說到了asyncawait只是迷惑你的一種幻象,我們必須手握辟邪寶劍斬開幻象顯真身,這里借助 ilspy 截圖如下:

圖片圖片

從卦中看,本質上就是借助AsyncTaskMethodBuilder<string> 建造者將 awaiter 和 stateMachine 做了一個綁定,感興趣的朋友可以追一下 AwaitUnsafeOnCompleted() 方法,最后狀態機 <UseAwaitAsync>d__1 實例會放入到 Task.Run 的 m_continuationObject 字段。如果有朋友對流程比較蒙的話,我畫了一張簡圖。

圖片圖片

圖和代碼都有了,接下來就是眼見為實。分別在 AddTaskContinuation 和 RunContinuations 方法中做好埋點,前者可以看到 延續任務 是怎么加進去的,后者可以看到 延續任務 是怎么取出來的。

圖片圖片

圖片圖片

心細的朋友會發現這卦上有一個很特別的地方,就是 allowInlining=true,也就是回調函數(StateMachine)是在當前線程上一擼到底的。

有些朋友可能要問,能不能讓延續任務 跑在單獨線程上?可以是可以,但你得把 Task.Run 改成 Task.Factory.StartNew ,這樣就可以設置TaskCreationOptions參數,參考代碼如下:

var html = await Task.Factory.StartNew(() =>{}, TaskCreationOptions.RunContinuationsAsynchronously);

2. ContinueWith

那些同處于被裁的35歲大齡程序員應該知道Task是 framework 4.0 時代出來的,而async,await是4.5出來的,所以在這個過渡期中有大量的項目會使用ContinueWith 導致回調地獄。。。這里我們對比一下兩者有何不同,先寫一段參考代碼。

internal class Program
    {
        static void Main(string[] args)
        {
            UseContinueWith();

            Console.ReadLine();
        }

        static Task<string> UseContinueWith()
        {
            var query = Task.Run(() =>
            {
                Thread.Sleep(1000);
                var response = "<html><h1>博客園</h1></html>";
                return response;
            }).ContinueWith(t =>
            {
                var html = t.Result;
                Console.WriteLine($"GetStringAsync 的結果:{html}");
                return html;
            });

            return query;
        }
    }

從卦代碼看確實沒有asyncawait簡潔,那 ContinueWith 內部做了什么呢?感興趣的朋友可以跟蹤一下,本質上和 StateMachine 的玩法是一樣的,都是借助 m_continuationObject 來實現延續,畫個簡圖如下:

圖片圖片

代碼和模型圖都有了,接下來就是用 dnspy 開干了。。。還是在 AddTaskContinuation 和 RunContinuations 上埋伏斷點觀察。

圖片圖片

圖片圖片

從卦中可以看到,延續任務使用新線程來執行的,并沒有一擼到底,這明顯與 asyncawait 的方式不同,有些朋友可能又要說了,那如何實現和StateMachine一樣的呢?這就需要在 ContinueWith 中新增 ExecuteSynchronously 同步參數,參考如下:

var query = Task.Run(() => { }).ContinueWith(t =>
    {
    }, TaskContinuationOptions.ExecuteSynchronously);

圖片圖片

3. Awaiter

使用Awaiter做任務延續的朋友可能相對少一點,它更多的是和 StateMachine 打配合,當然單獨使用也可以,但沒有前兩者靈活,它更適合那些不帶返回值的任務延續,本質上也是借助 m_continuationObject 字段實現的一套底層玩法,話不多說,上一段代碼:

static Task<string> UseAwaiter()
        {
            var awaiter = Task.Run(() =>
            {
                Thread.Sleep(1000);
                var response = "<html><h1>博客園</h1></html>";
                return response;
            }).GetAwaiter();

            awaiter.OnCompleted(() =>
            {
                var html = awaiter.GetResult();
                Console.WriteLine($"UseAwaiter 的結果:{html}");
            });

            return Task.FromResult(string.Empty);
        }

前面兩種我配了圖,這里沒有理由不配了,哈哈,模型圖如下:

圖片圖片

接下來把程序運行起來,觀察截圖:

圖片圖片

圖片圖片

從卦中觀察,它和StateMachine一樣,默認都是 一擼到底 的方式。

三、RunContinuations 觀察

這一小節我們單獨說一下 RunContinuations 方法,因為這里的實現太精妙了,不幸的是Dnspy和ILSpy反編譯出來的代碼太狗血,原汁原味的簡化后代碼如下:

private void RunContinuations(object continuationObject) // separated out of FinishContinuations to enable it to be inlined
    {
        bool canInlineContinuations =
            (m_stateFlags & (int)TaskCreationOptions.RunContinuationsAsynchronously) == 0 &&
            RuntimeHelpers.TryEnsureSufficientExecutionStack();

        switch (continuationObject)
        {
            // Handle the single IAsyncStateMachineBox case.  This could be handled as part of the ITaskCompletionAction
            // but we want to ensure that inlining is properly handled in the face of schedulers, so its behavior
            // needs to be customized ala raw Actions.  This is also the most important case, as it represents the
            // most common form of continuation, so we check it first.
            case IAsyncStateMachineBox stateMachineBox:
                AwaitTaskContinuation.RunOrScheduleAction(stateMachineBox, canInlineContinuations);
                LogFinishCompletionNotification();
                return;

            // Handle the single Action case.
            case Action action:
                AwaitTaskContinuation.RunOrScheduleAction(action, canInlineContinuations);
                LogFinishCompletionNotification();
                return;

            // Handle the single TaskContinuation case.
            case TaskContinuation tc:
                tc.Run(this, canInlineContinuations);
                LogFinishCompletionNotification();
                return;

            // Handle the single ITaskCompletionAction case.
            case ITaskCompletionAction completionAction:
                RunOrQueueCompletionAction(completionAction, canInlineContinuations);
                LogFinishCompletionNotification();
                return;
        }
    }

卦中的 case 挺有意思的,除了本篇聊過的 TaskContinuation 和 IAsyncStateMachineBox 之外,還有另外兩種 continuationObject,這里說一下 ITaskCompletionAction 是怎么回事,其實它是 Task.Result 的底層延續類型,所以大家應該能理解為什么 Task.Result 能喚醒,主要是得益于Task.m_continuationObject =completionAction 所致。

說了這么說,如何眼見為實呢?可以從源碼中尋找答案。

private bool SpinThenBlockingWait(int millisecondsTimeout, CancellationToken cancellationToken)
        {
            var mres = new SetOnInvokeMres();

            AddCompletionAction(mres, addBeforeOthers: true);

            var returnValue = mres.Wait(Timeout.Infinite, cancellationToken);
        }

        private sealed class SetOnInvokeMres : ManualResetEventSlim, ITaskCompletionAction
        {
            internal SetOnInvokeMres() : base(false, 0) { }
            public void Invoke(Task completingTask) { Set(); }
            public bool InvokeMayRunArbitraryCode => false;
        }

從卦中可以看到,其實就是把 ITaskCompletionAction 接口的實現類 SetOnInvokeMres 塞入了 Task.m_continuationObject 中,一旦Task執行完畢之后就會調用 Invoke() 下的 Set() 來實現事件喚醒。

四、總結

雖然異步任務延續有三種實現方法,但底層都是一個套路,即借助 Task.m_continuationObject 字段玩出的各種花樣,當然他們也是有一些區別的,即對 m_continuationObject 任務是否用單獨的線程調度,產生了不同的意見分歧。

責任編輯:武曉燕 來源: 一線碼農聊技術
相關推薦

2022-09-26 08:03:25

VMware虛擬機

2023-03-31 09:29:18

代碼量統計代碼增刪

2021-05-12 18:02:23

方法創建線程

2024-10-08 10:55:04

2024-06-28 12:47:29

C#弱引用底層

2024-08-26 14:46:57

2021-03-29 00:02:10

C#Attribute元素

2024-12-26 10:05:58

C#前臺線程

2022-08-30 07:39:57

C++namespace隔離

2021-02-22 14:04:47

Vue框架項目

2023-11-04 16:28:54

2020-10-30 07:11:31

C 語言編程

2022-11-02 08:51:01

2023-12-07 07:26:04

2023-02-09 10:39:15

gRPC通信模式

2024-09-09 08:29:25

2024-01-02 13:26:39

TLSC#線程

2020-10-23 07:00:00

C++函數

2020-09-08 06:54:29

Java Gradle語言

2023-07-06 13:56:14

微軟Skype
點贊
收藏

51CTO技術棧公眾號

艳妇乳肉豪妇荡乳xxx| 黄色免费高清视频| 啦啦啦免费高清视频在线观看| 久久夜色电影| 日韩欧美中文字幕在线观看 | 一区二区三区四区免费视频| 国产精品久久久久久免费免熟| 欧美另类专区| 精品亚洲一区二区三区在线观看| 手机在线免费观看毛片| 超碰在线观看免费| 99麻豆久久久国产精品免费 | 日韩av超清在线观看| 亚洲视频你懂的| 久久亚洲高清| 999精品国产| 亚洲欧美久久| 不卡av在线网站| 真人bbbbbbbbb毛片| 欧美激情啪啪| 精品国产91久久久久久老师| 亚洲欧美久久234| 精品国产av一区二区| 免费中文字幕日韩欧美| 欧美剧在线观看| 免费在线观看污| 视频一区在线| 欧美日韩国产一二三| 日本免费黄视频| gogogogo高清视频在线| 国产清纯白嫩初高生在线观看91| 999在线免费观看视频| 国产精品xxxxxx| 黄色精品免费| 久久精品在线播放| 神马久久久久久久久久久| 麻豆一区二区| 日韩手机在线导航| 天天操天天干天天做| 新片速递亚洲合集欧美合集| 亚洲一区二区在线视频| 免费看av软件| 天堂а√在线官网| 国产欧美一区二区精品久导航 | 日韩精品一区二区三| 91精品电影| 中文字幕日韩免费视频| 免费在线观看污| 一本色道久久综合狠狠躁的番外| 精品国产乱码久久久久久1区2区| 久久久久xxxx| 精品三级在线| 91福利视频久久久久| 六月丁香激情网| av免费不卡国产观看| 伊人夜夜躁av伊人久久| 亚洲蜜桃在线| 91在线网址| 中文字幕av一区二区三区免费看| 美国av一区二区三区| 亚洲欧美日韩成人在线| 97久久精品人人做人人爽50路| julia一区二区中文久久94| 国产三级三级在线观看| 国产综合色视频| 成人性教育视频在线观看| 国产又粗又猛又黄又爽| 国产一区二区三区免费看| 18成人在线| 亚洲精品成人电影| 国产一区二区不卡老阿姨| 国产一区深夜福利| 99久久99久久久精品棕色圆| 国产一区二区三区高清播放| 亚洲一区二区三区四区在线播放| av网站免费播放| 成人免费福利片| 九色综合婷婷综合| 男女视频在线观看| 中文字幕不卡的av| 中国老女人av| 国产又色又爽又黄刺激在线视频| 性久久久久久久| 37pao成人国产永久免费视频| 三上悠亚一区二区| 欧美性一级生活| 色综合五月婷婷| 高清一区二区三区| 亚洲视频视频在线| 黄色录像一级片| 国产一在线精品一区在线观看| 韩国三级日本三级少妇99| 久久夜色精品国产噜噜亚洲av| 奇米在线7777在线精品| 96国产粉嫩美女| 色哟哟国产精品色哟哟| 国产人成一区二区三区影院| 91麻豆天美传媒在线| 九色porny丨国产首页在线| 在线视频中文字幕一区二区| 免费成人黄色大片| 人人香蕉久久| 日韩在线中文字幕| 国产一级二级三级视频| 久久精品123| 99久久精品久久久久久ai换脸| 青青草观看免费视频在线 | 亚洲第一综合网| 欧美韩日精品| 国产精品久久二区| 亚洲va欧美va| 国产精品嫩草久久久久| 国产婷婷一区二区三区| 日韩av黄色| 亚洲级视频在线观看免费1级| 成人做爰69片免网站| 精品动漫av| 国产女精品视频网站免费| 少妇高潮久久久| 国产精品久久久久久户外露出 | 99精品视频在线| 欧美一级淫片aaaaaaa视频| 国产精品久久综合青草亚洲AV| 99久久国产综合精品麻豆| 国产三级中文字幕| 全亚洲第一av番号网站| 亚洲成人黄色网| 91传媒免费观看| 久久久久91| 国产精品免费一区二区三区在线观看 | 中文字幕第15页| 首页亚洲欧美制服丝腿| 国产精品久久国产精品| 黄视频网站在线看| 欧美午夜精品一区二区蜜桃| 屁屁影院国产第一页| 欧美激情 亚洲a∨综合| 国产欧美va欧美va香蕉在| 亚洲 欧美 自拍偷拍| 亚洲激情综合网| 911福利视频| av在线不卡顿| 热久久这里只有精品| 日本毛片在线观看| 亚洲在线视频免费观看| 永久免费黄色片| 欧美激情国产在线| 国产精品一区二区久久久| 国产一区二区三区福利| 富二代精品短视频| 成人免费毛片日本片视频| 伊人久久综合| 国产一级二级三级精品| 高清电影在线观看免费| 日韩精品一区二区三区在线观看 | 玩弄中年熟妇正在播放| 9l视频自拍蝌蚪9l视频成人| 欧美另类第一页| 朝桐光av在线一区二区三区| 亚洲少妇30p| 久久国产这里只有精品| 久久精品国产大片免费观看| 国产精品日韩精品| 久操视频在线免费播放| 91精品国产手机| 青青草手机在线视频| 国产传媒一区在线| 国产日韩欧美精品在线观看| 嗯用力啊快一点好舒服小柔久久| 国模gogo一区二区大胆私拍| 视频二区在线观看| 欧美日韩一区免费| 日本欧美一区二区三区不卡视频| 蜜臀av在线播放一区二区三区| 亚洲精品9999| 国产精品18| 久久久久久久香蕉网| 无码国精品一区二区免费蜜桃| 欧美日韩免费在线| 三年中国中文观看免费播放| 久久se这里有精品| 日韩欧美一级在线| 欧美激情网址| 国产精品视频地址| 中文在线免费| 日韩av在线直播| 青青艹在线观看| 亚洲欧美日韩在线| 亚洲av成人无码一二三在线观看| 欧美专区18| 日本成人性视频| 福利欧美精品在线| 日本一欧美一欧美一亚洲视频| 98在线视频| 精品福利二区三区| 波多野结衣激情视频| 中文字幕一区二| 少妇被狂c下部羞羞漫画| 久久人人超碰| 9191国产视频| 久久综合影院| 99热国产免费| 成人啊v在线| 欧美激情视频给我| 番号在线播放| 亚洲国产精品va在线看黑人动漫| 超碰在线观看91| 一区2区3区在线看| 永久免费av无码网站性色av| 成人在线一区二区三区| 嫩草av久久伊人妇女超级a| 综合久久亚洲| 欧美性色黄大片人与善| 一区二区三区视频播放| 国产精品美乳在线观看| 韩国精品一区| 久久99国产综合精品女同| 久久手机免费观看| 欧美精品一区二区蜜臀亚洲| 中文字幕在线观看高清| 欧美日韩免费在线| 精品在线视频观看| 国产精品白丝在线| 亚洲国产无码精品| 成人看片黄a免费看在线| 红桃视频 国产| 视频一区二区欧美| 国产精品专区在线| 午夜久久久久| 在线播放豆国产99亚洲| 欧美美乳视频| 久久精品99久久| 中文字幕日韩高清在线| 91精品视频在线| 成人精品高清在线视频| 欧美最猛性xxxxx亚洲精品| 草美女在线观看| 久久国产精品网站| 日本a在线播放| 中文字幕欧美视频在线| 你懂的免费在线观看| 亚洲国产中文字幕久久网| 亚洲AV午夜精品| 日韩精品一区二区三区在线| 国产精品无码免费播放| 欧美人牲a欧美精品| 中文字幕第31页| 精品视频资源站| 五月婷婷激情五月| 欧美视频免费在线观看| 欧美另类一区二区| 狠狠色狠狠色综合日日小说| 国产午夜激情视频| 亚洲成a人v欧美综合天堂下载| 麻豆影视在线播放| 亚洲一区在线视频观看| 久久精品国产亚洲AV无码麻豆| 亚洲综合色在线| 国产第一页在线播放| 亚洲一本大道在线| 日韩欧美一区二区一幕| 精品免费在线视频| 麻豆精品久久久久久久99蜜桃| 色综合久久中文综合久久牛| 免费黄色小视频在线观看| 欧美伊人久久久久久午夜久久久久| 无码人妻一区二区三区免费| 91搞黄在线观看| 中文字幕 亚洲视频| 欧美精品aⅴ在线视频| 国产富婆一级全黄大片| 欧美va在线播放| 天天综合天天综合| 亚洲免费一在线| 岛国最新视频免费在线观看| 色悠悠久久88| 18加网站在线| 国产91精品青草社区| 午夜欧美巨大性欧美巨大| 国产精品一二三视频| 精品成人18| 精品欧美一区二区久久久伦| 国产在线日韩精品| 一本二本三本亚洲码| 欧美激情四色| 久久久精品在线视频| 蜜桃av噜噜一区| 天堂va欧美va亚洲va老司机| 91麻豆视频网站| 午夜精品久久久久99蜜桃最新版| 一区二区三区日韩欧美| 羞羞影院体验区| 欧美三级韩国三级日本一级| 国产ts人妖调教重口男| 日韩精品极品视频免费观看| 欧美性videos| 久久免费成人精品视频| 欧美中文字幕精在线不卡| 亚洲aⅴ男人的天堂在线观看| 人人精品亚洲| 午夜久久久久久久久久久| 香蕉久久国产| 红桃视频一区二区三区免费| 91毛片在线观看| 男女性高潮免费网站| 色先锋资源久久综合| 国产黄色美女视频| 亚洲偷欧美偷国内偷| 欧美aaa免费| 国产精品一区二区久久| 日韩激情毛片| 肉大捧一出免费观看网站在线播放 | 亚洲高清不卡| 日日噜噜夜夜狠狠| 91亚洲男人天堂| 国产成人久久久久| 91国偷自产一区二区三区成为亚洲经典| 91精品视频免费在线观看| 亚洲国产精品视频在线观看| 91精品专区| 91av视频在线播放| 欧美电影院免费观看| 午夜精品福利一区二区| 一区二区三区福利| 一级黄色大片免费看| 亚洲欧美一区二区三区久本道91| 精品免费囯产一区二区三区 | 国色天香2019中文字幕在线观看| 伊人久久精品| 日本在线成人一区二区| 99国产精品私拍| 精品无码人妻少妇久久久久久| 一区在线中文字幕| 中文字幕+乱码+中文字幕明步 | 天天操天天操天天| 欧美国产视频一区二区| 国产精品白丝久久av网站| 日韩资源av在线| 亚洲一区二区伦理| www.17c.com喷水少妇| 亚洲永久免费视频| 超碰在线观看av| 欧美高清视频在线播放| 精品中文字幕一区二区三区四区 | 亚洲精品欧美激情| 99热这里只有精品9| 久久视频免费观看| 亚洲日韩中文字幕一区| 一区二区日本伦理| 久草热8精品视频在线观看| 蜜桃av免费观看| 欧美日韩精品电影| 生活片a∨在线观看| 成人黄色在线免费| 小说区亚洲自拍另类图片专区 | 国产精品 欧美精品| 欧美xxxx黑人xyx性爽| 日韩精品资源二区在线| 精精国产xxxx视频在线中文版| 国产成人精品福利一区二区三区 | 台湾佬中文在线| 亚洲欧美在线免费| 成人做爰视频www网站小优视频| 欧美激情视频一区二区三区| 美女国产精品| 极品尤物一区二区| 91精品免费观看| av免费网站在线观看| 肥熟一91porny丨九色丨| 亚洲国产高清一区二区三区| 国产性生活毛片| 欧美日韩一区二区三区在线免费观看 | 欧美日韩午夜| 亚洲av人人澡人人爽人人夜夜| 亚洲在线免费播放| 日本天堂在线| 国产精品视频网址| 欧美激情自拍| 中文字幕在线观看网址| 色欧美日韩亚洲| 欧美人xxx| 国产高清一区二区三区| 久久国产免费| 亚洲一区电影在线观看| 亚洲成人a**站| 在线一区视频观看| 在线观看三级网站| av一区二区不卡| 老熟妇一区二区三区啪啪| 欧美成人四级hd版| 少妇久久久久| 国产精品v日韩精品v在线观看| 一区二区三区欧美| 青青草视频在线观看| 91在线免费视频| 国产一区二区三区成人欧美日韩在线观看 | 久草在线资源站资源站| 久久精品日产第一区二区三区精品版 | 日韩国产一区二区| 无码人妻丰满熟妇啪啪网站|