欧美成人精品手机在线观看_69视频国产_动漫精品第一页_日韩中文字幕网 - 日本欧美一区二区

LOGO OA教程 ERP教程 模切知識(shí)交流 PMS教程 CRM教程 開發(fā)文檔 其他文檔  
 
網(wǎng)站管理員

深入解析C#異步編程:await 關(guān)鍵字背后的實(shí)現(xiàn)原理

freeflydom
2024年11月4日 10:26 本文熱度 675

C# 異步編程中 await 實(shí)現(xiàn)原理詳解

在C#中,async 和 await 關(guān)鍵字用于編寫異步代碼。本文將詳細(xì)介紹 await 的實(shí)現(xiàn)原理,包括狀態(tài)機(jī)的生成、回調(diào)函數(shù)的注冊和觸發(fā)等關(guān)鍵步驟。

1. 異步方法的基本概念

在C#中,async 關(guān)鍵字標(biāo)記一個(gè)方法為異步方法,而 await 關(guān)鍵字用于等待一個(gè)異步操作完成。異步方法可以提高程序的響應(yīng)性和性能,特別是在處理I/O操作和網(wǎng)絡(luò)請求時(shí)。

2. 示例異步方法

我們以一個(gè)簡單的異步方法為例,來詳細(xì)解釋 await 的實(shí)現(xiàn)原理。

public class Example
{
    public async Task<int> CalculateAsync()
    {
        int a = await Task.Run(() => 10);
        int b = await Task.Run(() => 20);
        return a + b;
    }
}

3. 編譯器生成的狀態(tài)機(jī)

編譯器會(huì)為每個(gè)異步方法生成一個(gè)狀態(tài)機(jī)。狀態(tài)機(jī)是一個(gè)結(jié)構(gòu)體,包含了異步方法的所有局部變量和狀態(tài)信息。

編譯器生成的狀態(tài)機(jī)類

public class Example
{
    public Task<int> CalculateAsync()
    {
        <CalculateAsync>d__0 stateMachine = new <CalculateAsync>d__0();
        stateMachine.<>4__this = this;
        stateMachine.<>t__builder = AsyncTaskMethodBuilder<int>.Create();
        stateMachine.<>1__state = -1;
        stateMachine.<>t__builder.Start(ref stateMachine);
        return stateMachine.<>t__builder.Task;
    }
    [StructLayout(LayoutKind.Auto)]
    [AsyncMethodBuilder(typeof(AsyncTaskMethodBuilder<int>))]
    private struct <CalculateAsync>d__0 : IAsyncStateMachine
    {
        public int <>1__state;
        public AsyncTaskMethodBuilder<int> <>t__builder;
        public Example <>4__this;
        public int <a>5__1;
        public TaskAwaiter<int> <>u__1;
        private void MoveNext()
        {
            int num = <>1__state;
            try
            {
                TaskAwaiter<int> awaiter;
                switch (num)
                {
                    case 0:
                        goto TR_0000;
                    case 1:
                        <>1__state = -1;
                        awaiter = <>u__1;
                        <>u__1 = default(TaskAwaiter<int>);
                        goto TR_0001;
                    case 2:
                        <>1__state = -1;
                        break;
                    default:
                        <>1__state = 0;
                        awaiter = Task.Run<int>(() => 10).GetAwaiter();
                        if (!awaiter.IsCompleted)
                        {
                            num = (<>1__state = 0);
                            <>u__1 = awaiter;
                            <>t__builder.AwaitUnsafeOnCompleted(ref awaiter, ref this);
                            return;
                        }
                        goto TR_0000;
                }
                TR_0000:
                <a>5__1 = awaiter.GetResult();
                awaiter = Task.Run<int>(() => 20).GetAwaiter();
                if (!awaiter.IsCompleted)
                {
                    num = (<>1__state = 1);
                    <>u__1 = awaiter;
                    <>t__builder.AwaitUnsafeOnCompleted(ref awaiter, ref this);
                    return;
                }
                TR_0001:
                int b = awaiter.GetResult();
                int result = <a>5__1 + b;
                <>1__state = -2;
                <>t__builder.SetResult(result);
            }
            catch (Exception exception)
            {
                <>1__state = -2;
                <>t__builder.SetException(exception);
            }
        }
        [DebuggerHidden]
        private void SetStateMachine(IAsyncStateMachine stateMachine)
        {
        }
    }
}

4. 實(shí)現(xiàn)流程詳解

初始化狀態(tài)機(jī)

在 CalculateAsync 方法中,創(chuàng)建狀態(tài)機(jī)實(shí)例 <CalculateAsync>d__0

<CalculateAsync>d__0 stateMachine = new <CalculateAsync>d__0();
stateMachine.<>4__this = this;
stateMachine.<>t__builder = AsyncTaskMethodBuilder<int>.Create();
stateMachine.<>1__state = -1;
  • <>4__this:指向當(dāng)前實(shí)例,即 Example 類的實(shí)例。
  • <>t__builder:創(chuàng)建 AsyncTaskMethodBuilder<int> 實(shí)例,用于管理任務(wù)的生命周期。
  • <>1__state:初始化狀態(tài)為 -1,表示方法尚未開始執(zhí)行。

開始執(zhí)行

調(diào)用 Start 方法開始執(zhí)行異步方法。Start 方法會(huì)調(diào)用狀態(tài)機(jī)的 MoveNext 方法。

stateMachine.<>t__builder.Start(ref stateMachine);

執(zhí)行方法體

在 MoveNext 方法中,根據(jù)當(dāng)前狀態(tài) <>1__state 執(zhí)行相應(yīng)的代碼。

private void MoveNext()
{
    int num = <>1__state;
    try
    {
        TaskAwaiter<int> awaiter;
        switch (num)
        {
            // 處理不同的狀態(tài)
        }
    }
    catch (Exception exception)
    {
        <>1__state = -2;
        <>t__builder.SetException(exception);
    }
}

遇到 await

遇到第一個(gè) await 關(guān)鍵字時(shí),調(diào)用 Task.Run(() => 10).GetAwaiter() 獲取 Awaiter 對象。

awaiter = Task.Run<int>(() => 10).GetAwaiter();
  • 檢查 awaiter.IsCompleted,如果任務(wù)已經(jīng)完成,直接調(diào)用 awaiter.GetResult() 獲取結(jié)果。
  • 如果任務(wù)未完成,記錄當(dāng)前狀態(tài) <>1__state,保存 awaiter 對象,并調(diào)用 <>t__builder.AwaitUnsafeOnCompleted 注冊回調(diào)。
if (!awaiter.IsCompleted)
{
    num = (<>1__state = 0);
    <>u__1 = awaiter;
    <>t__builder.AwaitUnsafeOnCompleted(ref awaiter, ref this);
    return;
}

注冊回調(diào)

AwaitUnsafeOnCompleted 方法會(huì)注冊一個(gè)回調(diào),當(dāng)任務(wù)完成時(shí),回調(diào)會(huì)被觸發(fā)。

public void AwaitUnsafeOnCompleted<TAwaiter, TStateMachine>(ref TAwaiter awaiter, ref TStateMachine stateMachine)
    where TAwaiter : ICriticalNotifyCompletion
    where TStateMachine : IAsyncStateMachine
{
    awaiter.UnsafeOnCompleted(stateMachine.MoveNext);
}
  • awaiter.UnsafeOnCompleted 方法注冊一個(gè)回調(diào)函數(shù),該回調(diào)函數(shù)會(huì)在任務(wù)完成時(shí)被觸發(fā)。
  • stateMachine.MoveNext 是一個(gè)委托,指向狀態(tài)機(jī)的 MoveNext 方法。

任務(wù)完成

當(dāng)任務(wù)完成時(shí),回調(diào)會(huì)被觸發(fā),重新調(diào)用 MoveNext 方法,恢復(fù)異步方法的執(zhí)行。

public void OnCompleted(Action continuation)
{
    task.ContinueWith(_ => continuation(), TaskScheduler.Default);
}

繼續(xù)執(zhí)行

從上次暫停的地方繼續(xù)執(zhí)行方法體。

TR_0000:
<a>5__1 = awaiter.GetResult();
awaiter = Task.Run<int>(() => 20).GetAwaiter();
if (!awaiter.IsCompleted)
{
    num = (<>1__state = 1);
    <>u__1 = awaiter;
    <>t__builder.AwaitUnsafeOnCompleted(ref awaiter, ref this);
    return;
}
  • 遇到第二個(gè) await 關(guān)鍵字時(shí),重復(fù)上述步驟。

方法完成

當(dāng)所有異步操作完成并計(jì)算出結(jié)果后,設(shè)置狀態(tài) <>1__state 為 -2,表示方法已經(jīng)完成。

int b = awaiter.GetResult();
int result = <a>5__1 + b;
<>1__state = -2;
<>t__builder.SetResult(result);
  • 調(diào)用 <>t__builder.SetResult 設(shè)置任務(wù)的結(jié)果。
  • 如果在執(zhí)行過程中拋出異常,捕獲異常并調(diào)用 <>t__builder.SetException 設(shè)置任務(wù)的異常。
catch (Exception exception)
{
    <>1__state = -2;
    <>t__builder.SetException(exception);
}

5. 深入理解 AsyncTaskMethodBuilder

AsyncTaskMethodBuilder 是一個(gè)輔助類,用于構(gòu)建和管理異步方法的任務(wù)。它提供了以下方法:

  • Create:創(chuàng)建一個(gè)新的 AsyncTaskMethodBuilder 實(shí)例。
  • Start:開始執(zhí)行異步方法,調(diào)用狀態(tài)機(jī)的 MoveNext 方法。
  • AwaitUnsafeOnCompleted:注冊回調(diào)函數(shù),當(dāng)任務(wù)完成時(shí)觸發(fā)回調(diào)。
  • SetResult:設(shè)置任務(wù)的結(jié)果。
  • SetException:設(shè)置任務(wù)的異常。

AsyncTaskMethodBuilder 的內(nèi)部實(shí)現(xiàn)

AsyncTaskMethodBuilder 內(nèi)部維護(hù)了一個(gè) Task 對象,用于表示異步操作的結(jié)果。當(dāng)異步方法完成時(shí),SetResult 方法會(huì)設(shè)置任務(wù)的結(jié)果,SetException 方法會(huì)設(shè)置任務(wù)的異常。

public struct AsyncTaskMethodBuilder<TResult>
{
    private Task<TResult> task;
    public static AsyncTaskMethodBuilder<TResult> Create()
    {
        return new AsyncTaskMethodBuilder<TResult>(new Task<TResult>());
    }
    private AsyncTaskMethodBuilder(Task<TResult> task)
    {
        this.task = task;
    }
    public void Start<TStateMachine>(ref TStateMachine stateMachine)
        where TStateMachine : IAsyncStateMachine
    {
        stateMachine.MoveNext();
    }
    public void AwaitOnCompleted<TAwaiter, TStateMachine>(ref TAwaiter awaiter, ref TStateMachine stateMachine)
        where TAwaiter : INotifyCompletion
        where TStateMachine : IAsyncStateMachine
    {
        awaiter.OnCompleted(stateMachine.MoveNext);
    }
    public void AwaitUnsafeOnCompleted<TAwaiter, TStateMachine>(ref TAwaiter awaiter, ref TStateMachine stateMachine)
        where TAwaiter : ICriticalNotifyCompletion
        where TStateMachine : IAsyncStateMachine
    {
        awaiter.UnsafeOnCompleted(stateMachine.MoveNext);
    }
    public void SetResult(TResult result)
    {
        task.SetResult(result);
    }
    public void SetException(Exception exception)
    {
        task.SetException(exception);
    }
    public Task<TResult> Task => task;
}

6. 異步方法的生命周期

異步方法的生命周期可以分為以下幾個(gè)階段:

  1. 初始化:創(chuàng)建狀態(tài)機(jī)實(shí)例,初始化狀態(tài)和任務(wù)構(gòu)建器。
  2. 開始執(zhí)行:調(diào)用 Start 方法開始執(zhí)行異步方法。
  3. 執(zhí)行方法體:在 MoveNext 方法中,根據(jù)當(dāng)前狀態(tài)執(zhí)行相應(yīng)的代碼。
  4. 遇到 await:檢查任務(wù)是否完成,如果未完成則注冊回調(diào)并暫停方法執(zhí)行。
  5. 任務(wù)完成:回調(diào)被觸發(fā),重新調(diào)用 MoveNext 方法,恢復(fù)異步方法的執(zhí)行。
  6. 方法完成:所有異步操作完成,設(shè)置任務(wù)的結(jié)果或異常。

7. 異步方法的優(yōu)勢

使用 async 和 await 編寫的異步方法有以下優(yōu)勢:

  • 提高響應(yīng)性:異步方法不會(huì)阻塞主線程,應(yīng)用程序可以繼續(xù)響應(yīng)用戶的輸入和其他事件。
  • 提高性能:異步方法可以并發(fā)執(zhí)行多個(gè)任務(wù),充分利用系統(tǒng)資源。
  • 簡化代碼:異步方法的代碼結(jié)構(gòu)類似于同步方法,易于理解和維護(hù)。

8. 異步方法的注意事項(xiàng)

盡管 async 和 await 提供了許多優(yōu)勢,但在使用時(shí)也需要注意以下幾點(diǎn):

  • 避免 async voidasync void 方法主要用于事件處理程序,其他情況下應(yīng)避免使用,因?yàn)樗鼰o法被等待,并且異常處理較為困難。
  • 異常處理:異步方法中的異常會(huì)被包裝在 AggregateException 中,需要特殊處理。
  • 資源管理:異步方法中使用 using 語句時(shí),需要注意 Dispose 方法的調(diào)用時(shí)機(jī)。

9. 完整的流程圖

為了更好地理解這個(gè)過程,可以用流程圖來展示:

總結(jié)

通過上述詳細(xì)的解釋和示例代碼,我們可以總結(jié)出以下幾點(diǎn):

  1. 異步方法的基本概念async 和 await 關(guān)鍵字用于編寫異步代碼。
  2. 狀態(tài)機(jī)的生成:編譯器為每個(gè)異步方法生成一個(gè)狀態(tài)機(jī),包含所有局部變量和狀態(tài)信息。
  3. MoveNext 方法的執(zhí)行MoveNext 方法是狀態(tài)機(jī)的核心,負(fù)責(zé)管理和執(zhí)行異步操作。
  4. 回調(diào)函數(shù)的注冊和觸發(fā)
    • 當(dāng)遇到 await 關(guān)鍵字時(shí),編譯器會(huì)生成代碼來檢查任務(wù)是否已經(jīng)完成。
    • 如果任務(wù)未完成,注冊回調(diào)并暫停方法執(zhí)行。
    • 當(dāng)任務(wù)完成時(shí),回調(diào)函數(shù)會(huì)被觸發(fā),重新調(diào)用狀態(tài)機(jī)的 MoveNext 方法,從而恢復(fù)異步方法的執(zhí)行。
  5. AwaitUnsafeOnCompleted 方法的作用:在任務(wù)完成時(shí)注冊一個(gè)回調(diào)函數(shù),回調(diào)函數(shù)會(huì)在任務(wù)完成后被觸發(fā),從而恢復(fù)異步方法的執(zhí)行。

轉(zhuǎn)自?https://www.cnblogs.com/Bob-luo/p/18518463


該文章在 2024/11/4 10:26:31 編輯過
關(guān)鍵字查詢
相關(guān)文章
正在查詢...
點(diǎn)晴ERP是一款針對中小制造業(yè)的專業(yè)生產(chǎn)管理軟件系統(tǒng),系統(tǒng)成熟度和易用性得到了國內(nèi)大量中小企業(yè)的青睞。
點(diǎn)晴PMS碼頭管理系統(tǒng)主要針對港口碼頭集裝箱與散貨日常運(yùn)作、調(diào)度、堆場、車隊(duì)、財(cái)務(wù)費(fèi)用、相關(guān)報(bào)表等業(yè)務(wù)管理,結(jié)合碼頭的業(yè)務(wù)特點(diǎn),圍繞調(diào)度、堆場作業(yè)而開發(fā)的。集技術(shù)的先進(jìn)性、管理的有效性于一體,是物流碼頭及其他港口類企業(yè)的高效ERP管理信息系統(tǒng)。
點(diǎn)晴WMS倉儲(chǔ)管理系統(tǒng)提供了貨物產(chǎn)品管理,銷售管理,采購管理,倉儲(chǔ)管理,倉庫管理,保質(zhì)期管理,貨位管理,庫位管理,生產(chǎn)管理,WMS管理系統(tǒng),標(biāo)簽打印,條形碼,二維碼管理,批號(hào)管理軟件。
點(diǎn)晴免費(fèi)OA是一款軟件和通用服務(wù)都免費(fèi),不限功能、不限時(shí)間、不限用戶的免費(fèi)OA協(xié)同辦公管理系統(tǒng)。
Copyright 2010-2025 ClickSun All Rights Reserved