精品视频在线免费观看_国产精品资源网_欧美日韩亚洲综合在线_自拍视频国产精品

原創生活

國內 商業 滾動

基金 金融 股票

期貨金融

科技 行業 房產

銀行 公司 消費

生活滾動

保險 海外 觀察

財經 生活 期貨

當前位置:行業 >

全球看點:ET框架6.0分析二、異步編程

文章來源:博客園  發布時間: 2023-05-15 09:20:32  責任編輯:cfenews.com
+|-
概述

ET框架很多地方都用到了異步,例如資源加載、AI、Actor模型等等。ET框架對C#的異步操作進行了一定程度的封裝和改造,有一些特點:

顯式的或者說強調了使用C#異步實現協程機制(其實C#的異步編程天生就能實現這種用法)強制單線程異步沒有使用C#庫的Task,自己實現了ETTask等類實現了協程鎖

為了更好的理解下面的內容,推薦先看一下之前寫的這兩篇文章:

關于異步對CallbackHell的優化 跳轉鏈接:《Lua CallbackHell優化》關于C#異步編程介紹和底層實現(最好看下,不然下面有些內容不太好理解) 跳轉鏈接:《C# 異步編程async/await》ETTask

C# 的異步函數有三個返回值(現在好像.NET7又多了一個ValueTask):Task,Task,void,對應的,ET框架也一樣對應實現了:ETTask,ETTask/,ETVoid,其實現相比C#簡化了一些邏輯,并添加一些新的特性以適應ET框架,其實使用起來是差不多的。為了實現ETTask,也實現了對應AsyncTaskCompletedMethodBuilder的AsyncETTaskCompletedMethodBuilder等類(其實還C#原來的邏輯差不太多,有興趣可以看下上述C# 異步編程的鏈接)。


【資料圖】

ETTask添加了一些特性:

支持對象池顯式強調協程
[DebuggerHidden]private async ETVoid InnerCoroutine(){    await this;}[DebuggerHidden]public void Coroutine(){    InnerCoroutine().Coroutine();}

可以看到這里的所謂協程Coroutine,其實等效于 await task,只是平平無奇的異步調用罷了

異常消息打印同步上線文 SynchronizationContext

C#異步編程在大多數情況下會使用多線程,ET的異步操作例如定時器等,使用多線程的開銷相比較大,且ET框架是多進程,性能是分攤到多個進程中。所以ET使用了單線程的異步。

ThreadSynchronizationContext繼承自SynchronizationContext,在構造初始化是會把自身設為當前SynchronizationContext.Current,重寫了Post(異步消息分派到同步上下文)方法,來改寫異步消息的分派到當前線程(就是進入隊列)。

而異步函數在執行時,會獲取當前上下文(__builder.AwaitUnsafeOnCompleted方法會調用GetCompletionAction,內部調用ExecutionContext.FastCapture(),這個方法內部捕獲SynchronizationContext,感興趣可以關鍵詞搜索下)

public class ThreadSynchronizationContext : SynchronizationContext{    // 線程同步隊列,發送接收socket回調都放到該隊列,由poll線程統一執行    private readonly ConcurrentQueue queue = new ConcurrentQueue();    private Action a;    public void Update()    {        while (true)        {            if (!this.queue.TryDequeue(out a))            {                return;            }            try            {                a();            }            catch (Exception e)            {                Log.Error(e);            }        }    }    public override void Post(SendOrPostCallback callback, object state)    {        this.Post(() => callback(state));    }        public void Post(Action action)    {        this.queue.Enqueue(action);    }}public class MainThreadSynchronizationContext: Singleton, ISingletonUpdate{    private readonly ThreadSynchronizationContext threadSynchronizationContext = new ThreadSynchronizationContext();    public MainThreadSynchronizationContext()    {        SynchronizationContext.SetSynchronizationContext(this.threadSynchronizationContext);    }        public void Update()    {        this.threadSynchronizationContext.Update();    }        public void Post(SendOrPostCallback callback, object state)    {        this.Post(() => callback(state));    }        public void Post(Action action)    {        this.threadSynchronizationContext.Post(action);    }}// MainThreadSynchronizationContext.Instance.Update()Game.Update();

ThreadSynchronizationContex由包裹的MainThreadSynchronizationContext驅動更新,MainThreadSynchronizationContext是個單件,由外面驅動。更新Update方法會把隊列里的委托取出執行。

SynchronizationContext

假設有兩個線程,一個UI線程,一個后臺線程,一個業務先在后臺線程計算數據,然后在UI線程中刷新顯示數據,顯然不同的線程其上下文環境是不同的,兩個線程的通信可以使用SynchronizationContext完成。SynchronizationContext官方文檔 https://learn.microsoft.com/zh-CN/dotnet/api/system.threading.synchronizationcontext?view=netcore-3.0

協程鎖

多線程編程,對公共資源的訪問要加鎖,以保證數據訪問的安全。類似的,在ET的異步編程中,從雖然上文中可以了解到ET的異步其實是單線程的,從代碼運行的層面其實是一個線程以某種順序處理一個個的任務,但是這種“順序”并不可控。ET這里的協程鎖其實就是使用某個key,對所有用這個key包裹的代碼段推入一個隊列,只有前面的代碼段執行結束才能執行后面的代碼。

這看起來和C#平時用的lock(object),其實只是用法上比較像,其實在實現細節是有根本的差距的:簡單來說。ET實現的協程鎖是一種用戶態的鎖,不會造成內核態/用戶態的切換。而lock是一種C#語法糖,在編譯時其實是通過Monitor監視器實現的,會涉及到內核轉換。一個線程上可能會運行成百上千個協程,如果這個線程被掛起,那么有可能造成很多協程Delay,可能造成災難性的后果。

結構類圖:時序圖:結合ET工程官方的一個用法:

public static async ETTask Query(this DBComponent self, long id, string collection = null) where T : Entity{    using (await CoroutineLockComponent.Instance.Wait(CoroutineLockType.DB, id % DBComponent.TaskCount))    {        IAsyncCursor cursor = await self.GetCollection(collection).FindAsync(d => d.Id == id);        return await cursor.FirstOrDefaultAsync();    }}

可以看到協程鎖是被using包裹的,即{}包裹的代碼塊運行結束,協程鎖會被dispose。先來看當第一次調用Wait時會直接返回,當第一次的鎖沒有被dispose時,后面獲取鎖時會進入隊列。當前面的鎖被dispose時,會通知隊列中后面一個鎖在下一次Update時被Notify,SetResult獲取到鎖,其所屬的代碼段得以執行。

關鍵詞:

專題首頁|財金網首頁

投資
探索

精彩
互動

獨家
觀察

京ICP備2021034106號-38   營業執照公示信息  聯系我們:55 16 53 8 @qq.com 關于我們 財金網  版權所有  cfenews.com
主站蜘蛛池模板: 久久久中精品2020中文| 久久久久久久少妇| 91久久久久久国产精品| 91国产在线精品| 一级日韩一区在线观看| 在线不卡视频一区二区| 国产精品美乳一区二区免费| 欧洲精品在线一区| 亚洲中文字幕无码专区| 亚洲a级在线观看| 日韩一区国产在线观看| 欧美国产综合在线V| 亚洲伊人久久综合| 欧美激情第三页| 国产欧美日韩一区| 欧美激情中文网| 国产精品一区电影| 欧美在线视频一二三| 国产精品美女免费| 国产亚洲精品网站| 久久精视频免费在线久久完整在线看| 久久免费精品视频| 久久久久久av| 88国产精品欧美一区二区三区| 日本欧洲国产一区二区| 国产精品一区免费观看| 日本亚洲欧洲色α| 国产精品精品久久久久久| 欧美日韩亚洲一区二区三区在线观看| 欧美成人精品在线| 不卡av在线网站| 99精品国产一区二区| 精品一区久久久| 日韩一区二区久久久| 久久久精品有限公司| 91精品视频在线| 国产精品热视频| 91久久久亚洲精品| 欧美日韩电影在线观看| 亚洲综合在线小说| 国产日韩在线亚洲字幕中文|