在 C# 中如何運用 async 和 await 進行非同步處理

在現今的程式開發中,非同步處理成為一個不可或缺的一部分。不論是網頁應用程式、手機還是桌面應用程式,很多時候我們需要進行長時間的處理,比如資料庫連線、讀取檔案,甚至是呼叫API,如果使用同步方式來進行,會導致我們的應用程式無法地回應使用者的動作,甚至出現「無回應」的情況。這時候,C# 提供的 async和 await關鍵字就派上用場了,搭配這兩個關鍵字使用,就可以讓非同步作要做的事情,也不會讓UI卡住,來看看這兩個關鍵字要怎麼使用。

為何使用 async 和 await?

首先,讓我們簡單了解一下 async 和 await 的基本概念。async 是一個修飾符,用來標註一個方法可以執行非同步操作,而 await 則是用來等待一個非同步操作完成。這兩個關鍵字的組合可以讓我們更容易寫出非同步程式碼,並且保持程式碼的可讀性。

async 和 await 的基本用法

要定義一個非同步方法時,首先需要在方法前面添加 async 修飾詞。這告訴編譯器,這個方法將使用非同步編程模型。

定義非同步方法

C#
static async Task<string> DoSomeThingAsync()
{
    Console.WriteLine($"做其他件事情");

    await Task.Delay(3000); // 等待 3 秒  

    return $"做其他件事情已經完成";
}

在上面的程式碼,使用了 async 來標記方法 DoSomeThingAsync。這個方法會返回一個 Task<string>,表示它做完這件事情之後就會返回字串。

呼叫非同步方法

C#
static async Task Main(string[] args)
{
    Console.WriteLine("最第一件事情");

    string SomeThingStatus = await DoSomeThingAsync();

    // 下單後可以去做其他事情  
    Console.WriteLine("最第二件事情");

    // 顯示訂單狀態  
    Console.WriteLine(SomeThingStatus);
}

接下來,我們使用 await 關鍵字來非同步地抓資料,但不會阻塞主執行緒,使用者仍然可以在等待過程中與 UI 互動,當這個Task完成,SomeThingStatus的變數可以拿到執行的結果。

搭配Task.WhenAll()與Task.WhenAny()

Task.WhenAll()

當你開始熟悉 async await,你可以進一步探索它們在多個非同步操作中的使用。例如,當你需要同時發起多個Thread時,你可以使用 Task.WhenAll() 方法來等待所有的Task都完成:

C#
static async Task Main(string[] args)
{
    var task1 = DoSomeThingAAsync("第一件", 3000);
    var task2 = DoSomeThingAAsync("第二件", 5000);

    var result = await Task.WhenAll(task1, task2);
    Console.WriteLine(result);

}

static async Task<string> DoSomeThingAAsync(string name, int time)
{
    Console.WriteLine($"做{name}事情");

    // 使用 Task.Delay 模擬延遲
    await Task.Delay(time); // 等待 3 秒  

    return $"做{name}已經完成";
}
Task.WhenAny()執行結果

這段程式碼同時執行兩個Task,分別等待3秒跟5秒,利用Task.WhenAll可以讓等兩個Task執行完,最後再印出結果

Task.WhenAny()

等待多個Task時,Task.WhenAny只會返回任一個完成的Task,而不會等待所有Task。如果有多個Task同時完成,Task.WhenAny 仍然僅僅返回任意一個,並且會忽略其他Task的完成狀態。

C#
static async Task Main(string[] args)
{
    var task1 = DoSomeThingAAsync("第一件", 3000);
    var task2 = DoSomeThingAAsync("第二件", 5000);

    var result = await Task.WhenAny(task1, task2);
    Console.WriteLine(result.Result);
}

static async Task<string> DoSomeThingAAsync(string name, int time)
{
    Console.WriteLine($"做{name}事情");

    // 使用 Task.Delay 模擬延遲
    await Task.Delay(time); // 等待 3 秒  

    return $"做{name}已經完成";
}

這段程式碼同時執行兩個Task,分別等待3秒跟5秒,利用Task.WhenAny只會返回其中一個Task的結果。


分享這篇文章

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *