2024-09-23|閱讀時間 ‧ 約 22 分鐘

C# Async Programming的注意事項

以下是我在撰寫 C# Async Programming 會關注到的事項,我也是從別人的經驗學來的,也許值得參考。

全面擁抱異步

  • 一旦開始使用 async/await,就應該讓整個應用程序都使用異步模式。
  • 避免混合同步和異步代碼,這可能導致性能問題和 Deadlock。
    • 性能問題:因為 Calling Thread 沒有被釋放。導致桌面應用程式的 UI 凍結;導致 ASP .NET Core 不能服務更多的請求。
    • Deadlock:互相的等待對方釋放資源,造成程式卡住,不會執行後續的程式碼。
// 好的做法
public async Task<int> DoSomethingAsync()
{
var result = await CallDependencyAsync();
return result + 1;
}

// 避免這樣做
public int DoSomething()
{
var result = CallDependencyAsync().Result; // 可能導致死鎖
return result + 1;
}

避免使用 async void

  • 異步方法總是返回 Task 或 Task<T>,而不是 void。
  • async void 可能導致未處理的異常,造成應用程序崩潰。
// 好的做法
public async Task BackgroundOperationAsync()
{
var result = await CallDependencyAsync();
DoSomething(result);
}

// 避免這樣做
public async void BackgroundOperation() // 可能導致未捕獲的異常
{
var result = await CallDependencyAsync();
DoSomething(result);
}

絕不使用 Task.Result 或 Task.Wait

  • 這些方法可能在 UI 應用程序中造成 Deadlock,在服務器應用程序中導致線程池資源耗盡。
  • 始終使用 await 替代。
// 好的做法
public async Task<string> GetDataAsync()
{
var result = await FetchDataAsync();
return ProcessData(result);
}

// 避免這樣做
public string GetData()
{
var result = FetchDataAsync().Result; // 可能導致死鎖
return ProcessData(result);
}

正確傳遞 CancellationToken

將 CancellationToken 參數傳遞給支援的 API。

public async Task<string> DoAsyncThing(CancellationToken cancellationToken = default)
{
byte[] buffer = new byte[1024];
// 正確地將 cancellationToken 傳遞給 ReadAsync
int read = await _stream.ReadAsync(buffer, 0, buffer.Length, cancellationToken);
return Encoding.UTF8.GetString(buffer, 0, read);
}

優先使用 async/await 而非直接返回 Task

使用 async/await 提供更好的異常處理。

// 好的做法
public async Task<int> DoSomethingAsync()
{
return await CallDependencyAsync();
}

// 避免這樣做,除非有性能考慮
public Task<int> DoSomething()
{
return CallDependencyAsync();
}

優先使用 await,不要直接回傳 Task

沒有必要對 Task.FromResult 使用 await,因為這會增加不必要的開銷。

// 好的做法
public Task<int> GetValueAsync()
{
return Task.FromResult(42);
}

// 避免這樣做
public async Task<int> GetValueAsync()
{
return await Task.FromResult(42); // 不必要的 await
}
分享至
成為作者繼續創作的動力吧!
© 2024 vocus All rights reserved.