狠狠色丁香婷婷综合尤物/久久精品综合一区二区三区/中国有色金属学报/国产日韩欧美在线观看 - 国产一区二区三区四区五区tv

LOGO OA教程 ERP教程 模切知識交流 PMS教程 CRM教程 開發文檔 其他文檔  
 
網站管理員

C# Async 和 Await 到底在做什么?

admin
2024年12月7日 8:8 本文熱度 345

1. 引言

在C#中,asyncawait關鍵字是用于實現異步編程的強大工具。它們的引入極大地簡化了異步代碼的編寫,使得開發人員能夠更容易地創建響應式和高性能的應用程序。但是,要真正理解它們的工作原理,我們需要深入探討它們在底層到底在做什么。

2. 異步編程的基本概念

在深入asyncawait之前,我們需要理解一些基本概念:

  • 同步執行: 代碼按順序執行,每個操作完成后才會進行下一個。

  • 異步執行: 允許長時間運行的操作在后臺進行,而不阻塞主線程。

  • 任務(Task): 表示一個異步操作。

  • 線程: 程序執行的最小單位。

3. Async 和 Await 的基本用法

讓我們從一個簡單的例子開始:

static async Task Main(string[] args)
{
    var context = await GetWebContentAsync("http://www.baidu.com");
    Console.WriteLine(context);
}

public static async Task<string> GetWebContentAsync(string url)
{
    using (var client = new HttpClient())
    {
        string content = await client.GetStringAsync(url);
        return content;
    }
}

在這個例子中:

  • async關鍵字標記方法為異步方法。

  • 方法返回Task,表示一個最終會產生string的異步操作。

  • await用于等待GetStringAsync方法完成,而不阻塞線程。

4. Async 方法的轉換過程

當你使用async關鍵字標記一個方法時,編譯器會將其轉換為一個狀態機。這個過程大致如下:

  1. 創建一個實現了IAsyncStateMachine接口的結構體。

  2. 將方法體轉換為狀態機的MoveNext方法。

  3. 每個await表達式都成為一個可能的暫停點,對應狀態機中的一個狀態。

async方法如何被分解為多個步驟,每個await表達式對應一個狀態。

5. Await 的工作原理

await關鍵字的主要作用是:

  1. 檢查awaited任務是否已完成。

  2. 如果已完成,繼續執行后續代碼。

  3. 如果未完成,注冊一個回調并返回控制權給調用者。

讓我們通過一個例子來詳細說明:

public async Task DoWorkAsync()
{
    Console.WriteLine("開始工作");
    await Task.Delay(1000); // 模擬耗時操作
    Console.WriteLine("工作完成");
}

當執行到await Task.Delay(1000)時:

  1. 檢查Task.Delay(1000)是否已完成。

  2. 如果未完成:

    • 創建一個continuation(后續操作),包含`await`之后的代碼。

    • 將這個continuation注冊到Task上。

    • 返回控制權給調用者。

  3. Task.Delay(1000)完成時:

    • 觸發注冊的continuation。

    • 恢復執行`await`之后的代碼。

6. 異步方法的執行流程

讓我們通過一個更復雜的例子來理解異步方法的執行流程:

static async Task Main(string[] args)
{
    await MainMethodAsync();
    Console.ReadKey();
}

public static async Task MainMethodAsync()
{
    Console.WriteLine("1. 開始主方法");
    await Method1Async();
    Console.WriteLine("4. 主方法結束");
}

public static async Task Method1Async()
{
    Console.WriteLine("2. 開始方法1");
    await Task.Delay(1000);
    Console.WriteLine("3. 方法1結束");
}

執行流程如下:

  1. MainMethodAsync開始執行,打印"1. 開始主方法"。

  2. 遇到await Method1Async(),進入Method1Async

  3. Method1Async打印"2. 開始方法1"。

  4. 遇到await Task.Delay(1000),注冊continuation并返回。

  5. 控制權回到MainMethodAsync,但因為Method1Async未完成,所以MainMethodAsync也返回。

  6. 1秒后,Task.Delay完成,觸發continuation。

  7. Method1Async繼續執行,打印"3. 方法1結束"。

  8. Method1Async完成,觸發MainMethodAsync的continuation。

  9. MainMethodAsync繼續執行,打印"4. 主方法結束"。

7. 異常處理

async/await模式下的異常處理非常直觀。你可以使用常規的try/catch塊,異步方法中拋出的異常會被封裝在返回的Task中,并在await時重新拋出。

8. 避免常見陷阱

使用async/await時,有一些常見的陷阱需要注意:

8.1 死鎖

考慮以下代碼:

public async Task DeadlockDemoAsync()
{
    await Task.Delay(1000).ConfigureAwait(false);
}

public void CallAsyncMethod()
{
    DeadlockDemoAsync().Wait(); // 可能導致死鎖
}
  • 當在UI線程(或任何有同步上下文的線程)中調用CallAsyncMethod()時,會發生死鎖。

  • Wait()方法會阻塞當前線程,等待異步操作完成。

  • 當異步操作完成時,它默認會嘗試在原始的同步上下文(通常是UI線程)上繼續執行。

  • 但是原始線程已經被Wait()阻塞了,導致死鎖。

8.2 忘記await

public async Task ForgetAwaitDemoAsync()
{
    DoSomethingAsync(); // 忘記await
    Console.WriteLine("完成"); // 這行可能在異步操作完成之前執行
}

始終記得在異步方法調用前使用await

8.3 過度使用async void

除了事件處理程序外,應避免使用async void方法,因為它們的異常難以捕獲和處理。

public async void BadAsyncVoidMethod()
{
    await Task.Delay(1000);
    throw new Exception("這個異常很難被捕獲");
}

9. 高級模式

9.1 并行執行多個任務

使用Task.WhenAll可以并行執行多個異步任務:

public async Task ParallelExecutionDemo()
{
    var task1 = DoWorkAsync(1);
    var task2 = DoWorkAsync(2);
    var task3 = DoWorkAsync(3);

    await Task.WhenAll(task1, task2, task3);
    Console.WriteLine("所有任務完成");
}

public async Task DoWorkAsync(int id)
{
    await Task.Delay(1000);
    Console.WriteLine($"任務 {id} 完成");
}

9.2 帶超時的異步操作

使用Task.WhenAnyTask.Delay可以實現帶超時的異步操作:

static async Task Main(string[] args)
{
    await FetchDataWithTimeoutAsync("http://www.google.com",new TimeSpan(003));
    Console.ReadKey();
}

static async Task<string> FetchDataWithTimeoutAsync(string url, TimeSpan timeout)
{
    using (var client = new HttpClient())
    {
        var dataTask = client.GetStringAsync(url);
        var timeoutTask = Task.Delay(timeout);

        var completedTask = await Task.WhenAny(dataTask, timeoutTask);
        if (completedTask == timeoutTask)
        {
            throw new TimeoutException("操作超時");
        }

        return await dataTask;
    }
}

10. 結論

asyncawait極大地簡化了C#中的異步編程,使得編寫高效、響應式的應用程序變得更加容易。通過將復雜的異步操作轉換為看似同步的代碼,它們提高了代碼的可讀性和可維護性。


該文章在 2024/12/9 18:38:49 編輯過
關鍵字查詢
相關文章
正在查詢...
點晴ERP是一款針對中小制造業的專業生產管理軟件系統,系統成熟度和易用性得到了國內大量中小企業的青睞。
點晴PMS碼頭管理系統主要針對港口碼頭集裝箱與散貨日常運作、調度、堆場、車隊、財務費用、相關報表等業務管理,結合碼頭的業務特點,圍繞調度、堆場作業而開發的。集技術的先進性、管理的有效性于一體,是物流碼頭及其他港口類企業的高效ERP管理信息系統。
點晴WMS倉儲管理系統提供了貨物產品管理,銷售管理,采購管理,倉儲管理,倉庫管理,保質期管理,貨位管理,庫位管理,生產管理,WMS管理系統,標簽打印,條形碼,二維碼管理,批號管理軟件。
點晴免費OA是一款軟件和通用服務都免費,不限功能、不限時間、不限用戶的免費OA協同辦公管理系統。
Copyright 2010-2025 ClickSun All Rights Reserved