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

在現今的程式開發中,非同步處理成為一個不可或缺的一部分。不論是網頁應用程式、手機還是桌面應用程式,很多時候我們需要進行長時間的處理,比如資料庫連線、讀取檔案,甚至是呼叫API,如果使用同步方式來進行,會導致我們的應用程式無法地回應使用者的動作,甚至出現「無回應」的情況。這時候,C# 提供的 async和 await關鍵字就派上用場了,搭配這兩個關鍵字使用,就可以讓非同步作要做的事情,也不會讓UI卡住,來看看這兩個關鍵字要怎麼使用。
為何使用 async 和 await?
首先,讓我們簡單了解一下 async 和 await 的基本概念。async 是一個修飾符,用來標註一個方法可以執行非同步操作,而 await 則是用來等待一個非同步操作完成。這兩個關鍵字的組合可以讓我們更容易寫出非同步程式碼,並且保持程式碼的可讀性。
async 和 await 的基本用法
要定義一個非同步方法時,首先需要在方法前面添加 async 修飾詞。這告訴編譯器,這個方法將使用非同步編程模型。
定義非同步方法
static async Task<string> DoSomeThingAsync()
{
Console.WriteLine($"做其他件事情");
await Task.Delay(3000); // 等待 3 秒
return $"做其他件事情已經完成";
}在上面的程式碼,使用了 async 來標記方法 DoSomeThingAsync。這個方法會返回一個 Task<string>,表示它做完這件事情之後就會返回字串。
呼叫非同步方法
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都完成:
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,分別等待3秒跟5秒,利用Task.WhenAll可以讓等兩個Task執行完,最後再印出結果
Task.WhenAny()
等待多個Task時,Task.WhenAny只會返回任一個完成的Task,而不會等待所有Task。如果有多個Task同時完成,Task.WhenAny 仍然僅僅返回任意一個,並且會忽略其他Task的完成狀態。
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的結果。



