掌握.NET 10中的Async/Await C#:可擴展應用程式的基本指南

現代軟體開發需要速度、回應和無與倫比的擴展性。 在網頁應用程式和企業解決方案的世界中,阻塞UI執行緒或霸佔伺服器資源是完全不可接受的。 這正是非同步程式設計的用武之地,由強大的C#中的非同步和等待關鍵字提供支援,成為不僅僅是一個功能,而是一個必不可少的架構基礎。
對於使用高效能的函式庫的開發人員來說,例如用於PDF生成、影像操作和OCR的Iron Software套件,理解如何撰寫非同步程式碼是利用.NET Task並行函式庫全部威力的關鍵。
我們將深入探討非同步/等待 C#的機制,探索這種範式轉移如何將緩慢的同步程式設計轉變為高吞吐量的非同步操作,並將這些關鍵概念與Iron Software如何幫助企業達到最大效能相聯繫。
非同步程式設計的基本原理
在非同步和等待之前,非同步操作是透過繁雜的回呼和手動任務類操作來管理的,這導致了複雜且容易出錯的程式碼。 C#的非同步程式設計簡化了這一點,因為它允許開發人員撰寫看起來像同步程式碼但實際上是非同步執行的程式碼。
兩個核心組成部分是:
async關鍵字:async修飾詞標記一個方法為非同步方法,該方法可以包含等待表達式。 至關重要的是,標記為async的方法不會自動在背景執行緒上運行。 它只是啟用編譯器生成一個複雜的狀態機,來管理程式碼的繼續。 非同步方法通常返回一個Task物件(Task或Task)來表示正在進行的非同步任務。
- await關鍵字:await關鍵字是魔法般的組件。 當遇到等待表達式時,該方法會檢查等待的任務是否已完成。 如果沒有,該方法會立即暫停執行並將控制權返回給調用方法(或調用者)。 這會釋放當前執行緒(通常是主執行緒或執行緒池執行緒)來處理其他請求或任務。 當任務完成時,方法的其餘部分將被註冊為一個延續,並被重新安排執行。
以下是一個基本的程式碼範例:
public static async Task<string> DownloadDataAsync(string url)
{
// The async keyword allows us to use await
using var client = new HttpClient();
// await task: Control returns to the caller while the HTTP call happens
string data = await client.GetStringAsync(url); // I/O-bound
// The code after the await expression runs once the task finishes
return $"Data length: {data.Length}";
}
// Modern entry point for console apps
public static async Task Main(string[] args)
{
// This is the static async task main entry point
var result = await DownloadDataAsync("https://api.example.com/data");
Console.WriteLine(result);
}public static async Task<string> DownloadDataAsync(string url)
{
// The async keyword allows us to use await
using var client = new HttpClient();
// await task: Control returns to the caller while the HTTP call happens
string data = await client.GetStringAsync(url); // I/O-bound
// The code after the await expression runs once the task finishes
return $"Data length: {data.Length}";
}
// Modern entry point for console apps
public static async Task Main(string[] args)
{
// This is the static async task main entry point
var result = await DownloadDataAsync("https://api.example.com/data");
Console.WriteLine(result);
}Imports System
Imports System.Net.Http
Imports System.Threading.Tasks
Public Module Program
Public Async Function DownloadDataAsync(url As String) As Task(Of String)
' The async keyword allows us to use await
Using client As New HttpClient()
' await task: Control returns to the caller while the HTTP call happens
Dim data As String = Await client.GetStringAsync(url) ' I/O-bound
' The code after the await expression runs once the task finishes
Return $"Data length: {data.Length}"
End Using
End Function
' Modern entry point for console apps
Public Async Function Main(args As String()) As Task
' This is the static async task main entry point
Dim result As String = Await DownloadDataAsync("https://api.example.com/data")
Console.WriteLine(result)
End Function
End Module使用靜態非同步任務主節點是現代標準,消除了使用舊方法如.Wait()或.Result來阻塞主執行緒的需求。
效能與Iron Software整合
雖然Task是非同步程式碼的標準返回類型,在.NET 10中高級非同步程式設計通常使用ValueTask來在同步完成可能性的"熱路徑"中取得顯著效能提升(例如,檢索快取值)。 ValueTask避免了記憶體分配,這對於高吞吐量應用程式來說至關重要。
將非同步操作應用於Iron Software
Iron Software產品,如IronOCR(光學字符識別)和IronPDF(PDF生成),是利用非同步調用的完美選擇。 如將大型HTML文件轉換為PDF或掃描數百頁圖像以識別文本的操作通常是CPU密集型任務或涉及文件系統I/O,從非同步方法中受益匪淺。
當您使用Iron Software提供的同步和非同步方法時,您確保您的應用程式保持高度響應。
考慮使用IronPDF來< a href="從指定的URL創建文件" target="_blank">https://ironpdf.com/how-to/url-to-pdf/">從指定的URL創建文件:
public static async Task GeneratePdfFromUrlAsync(string url, string outputFileName)
{
// 1. Initialize the renderer
var renderer = new IronPdf.ChromePdfRenderer();
// Optional: Set rendering options if needed (e.g., margins, headers)
renderer.RenderingOptions.PaperSize = IronPdf.Rendering.PdfPaperSize.A4;
// 2. The core asynchronous operation: Fetch and render the URL content
// This is an I/O-bound task that releases the calling thread.
var pdf = await renderer.RenderUrlAsPdfAsync(url);
// 3. Save the PDF file asynchronously
await Task.Run(() =>
{
// This is the synchronous method you confirmed exists
pdf.SaveAs(outputFileName);
});
}public static async Task GeneratePdfFromUrlAsync(string url, string outputFileName)
{
// 1. Initialize the renderer
var renderer = new IronPdf.ChromePdfRenderer();
// Optional: Set rendering options if needed (e.g., margins, headers)
renderer.RenderingOptions.PaperSize = IronPdf.Rendering.PdfPaperSize.A4;
// 2. The core asynchronous operation: Fetch and render the URL content
// This is an I/O-bound task that releases the calling thread.
var pdf = await renderer.RenderUrlAsPdfAsync(url);
// 3. Save the PDF file asynchronously
await Task.Run(() =>
{
// This is the synchronous method you confirmed exists
pdf.SaveAs(outputFileName);
});
}Imports System.Threading.Tasks
Imports IronPdf
Public Module PdfGenerator
Public Async Function GeneratePdfFromUrlAsync(url As String, outputFileName As String) As Task
' 1. Initialize the renderer
Dim renderer As New ChromePdfRenderer()
' Optional: Set rendering options if needed (e.g., margins, headers)
renderer.RenderingOptions.PaperSize = Rendering.PdfPaperSize.A4
' 2. The core asynchronous operation: Fetch and render the URL content
' This is an I/O-bound task that releases the calling thread.
Dim pdf = Await renderer.RenderUrlAsPdfAsync(url)
' 3. Save the PDF file asynchronously
Await Task.Run(Sub()
' This is the synchronous method you confirmed exists
pdf.SaveAs(outputFileName)
End Sub)
End Function
End Module使用非同步方法生成的PDF

通過利用RenderHtmlAsPdfAsync()非同步方法,我們防止應用程式在處理大型文件時凍結或阻塞。 這展示了如何高效地撰寫非同步程式碼以進行複雜處理。
最佳實踐和邊緣案例
1. 處理多個任務和I/O
為了最大化效率,當等待獨立的I/O綁定工作時,您應該同時啟動多個任務,例如從遠程伺服器抓取數據或執行資料庫查詢。
public async Task<string[]> FetchAllDataAsync(string url1, string url2)
{
// Creating tasks starts the async operation immediately
Task<string> taskA = DownloadDataAsync(url1);
Task<string> taskB = DownloadDataAsync(url2);
// Wait for all the tasks to complete simultaneously
string[] results = await Task.WhenAll(taskA, taskB);
return results;
}public async Task<string[]> FetchAllDataAsync(string url1, string url2)
{
// Creating tasks starts the async operation immediately
Task<string> taskA = DownloadDataAsync(url1);
Task<string> taskB = DownloadDataAsync(url2);
// Wait for all the tasks to complete simultaneously
string[] results = await Task.WhenAll(taskA, taskB);
return results;
}Option Strict On
Public Async Function FetchAllDataAsync(url1 As String, url2 As String) As Task(Of String())
' Creating tasks starts the async operation immediately
Dim taskA As Task(Of String) = DownloadDataAsync(url1)
Dim taskB As Task(Of String) = DownloadDataAsync(url2)
' Wait for all the tasks to complete simultaneously
Dim results As String() = Await Task.WhenAll(taskA, taskB)
Return results
End Function這是創建並行運行任務的標準模式,通過利用非阻塞非同步操作大幅加速應用程式的反應時間。
2. 同步上下文和ConfigureAwait(false)
當等候的任務完成時,默認行為是捕獲同步上下文並確保延續在同一執行緒上(如UI執行緒)運行。 這對於UI應用程式至關重要,但會在伺服器端或函式庫代碼中造成不必要的負擔。
使用ConfigureAwait(false)告訴運行時,等待調用之後的代碼可以在任何可用的執行緒池背景執行緒上恢復。 這對於函式庫開發人員來說是一項關鍵實踐,以確保非同步操作的最大效能:
// Critical for shared libraries to avoid deadlocks and improve throughput
var data = await GetVarDataFromRemoteServer().ConfigureAwait(false);
// This code continues on any thread, improving resource usage.// Critical for shared libraries to avoid deadlocks and improve throughput
var data = await GetVarDataFromRemoteServer().ConfigureAwait(false);
// This code continues on any thread, improving resource usage.' Critical for shared libraries to avoid deadlocks and improve throughput
Dim data = Await GetVarDataFromRemoteServer().ConfigureAwait(False)
' This code continues on any thread, improving resource usage.3. 非同步void的危險
非同步程式設計中的一個最重要的規則是,除了非同步事件處理程序外,絕對不要使用非同步void。 例如,按鈕點擊事件處理程序方法通常會使用非同步void:
private async void Button_Click(object sender, EventArgs e) // event handler
{
// This is one of the few places async void is acceptable
await GenerateReportAsync(html);
}private async void Button_Click(object sender, EventArgs e) // event handler
{
// This is one of the few places async void is acceptable
await GenerateReportAsync(html);
}Private Async Sub Button_Click(sender As Object, e As EventArgs) Handles Button.Click ' event handler
' This is one of the few places async void is acceptable
Await GenerateReportAsync(html)
End Sub強烈不建議將非同步void方法用於任何其他用途。 由於非同步void方法無法被等待,調用執行緒無法跟蹤其完成或可靠地處理異常,這會使錯誤處理出現問題。 對於所有其他非同步方法,始終返回Task或Task。
4. 異常處理
穩健的異常處理至關重要。 當非同步操作失敗時(例如,網路服務調用遇到錯誤),異常被儲存在任務物件中。 當您等待任務時,等待表達式會將異常重新拋出到當前執行緒(恢復延續的執行緒)上,允許標準的try...catch塊有效地工作以進行異常處理。
結論
C#中的非同步和等待模式是一種範式轉變的功能,使開發人員從脆弱的同步程式設計轉向韌性強且可擴展的非同步方法。 通過理解底層狀態機並遵循最佳實踐—如優先使用Task而非非同步void,在函式庫中使用ConfigureAwait(false),並正確實施異常處理—開發人員可以創建出色效能的應用程式,處理像Iron Software套件中那樣的複雜處理任務。
Iron Software致力於開發核心具有高效能非同步程式設計的產品,確保您的撰寫程式碼的實踐達到最大吞吐量。 探索Iron Software的世界,看看利用非同步任務處理如何大幅提升您的應用程式的速度和回應能力。
