使用IRON SUITE

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

! Async/Await C#

現代軟體開發要求速度、反應能力和無與倫比的可擴展性。 在 Web 應用程式和企業解決方案的世界中,阻塞 UI 線程或佔用伺服器資源是完全不可接受的。 這時由 C# 中強大的 async 和 await 關鍵字驅動的異步程式設計,就不只是一項功能,而是必須的架構基礎。

對於使用高效能函式庫的開發人員而言,例如用於 PDF生成、影像處理和 OCR 的 Iron Software Suite,瞭解如何撰寫異步程式碼是建立高效程式碼的關鍵,以充分利用 .NET Task Parallel Library 的全部功能。

我們將深入探討 async/ await C# 的力學,探索這種範式轉換如何將緩慢的同步程式設計轉換為高吞吐量的異步操作,並將這些關鍵概念與 Iron Software 如何幫助企業實現最高性能相聯繫。

異步程式設計的基礎

async和await之前,異步操作是透過繁瑣的回呼和手動的Task類別操作來管理,導致程式碼複雜且容易出錯。 C# 中的異步程式設計簡化了這一點,它允許開發人員編寫 looks 同步程式碼但行為異步的程式碼。

兩個核心部分為

1.async關鍵字:async修飾符將方法標記為可以包含 await 表達式的 async 方法。 最重要的是,將一個方法標記為 async 並不**會自動在背景線程上執行。 它只是讓編譯器產生一個精密的狀態機器,管理程式碼的延續。 非同步方法通常會傳回一個 Task 物件(Task 或 Task)。 ) 表示正在進行的非同步任務。

2.await關鍵字: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);
}
$vbLabelText   $csharpLabel

使用靜態同步任務 main 是現代的標準,省去了使用 .Wait() 或 .Result 等傳統方法阻斷主線程的需要。

效能與 Iron 軟體整合。

雖然 Task 是非同步程式碼的標準回傳類型,但在 .NET 10 中,高階非同步程式設計通常會使用 ValueTask。對於可能出現同步完成的"熱路徑"(例如,檢索快取值),可以顯著提高效能。 ValueTask 可避免記憶體分配,因此對於高吞吐量的應用程式至關重要。

將異步操作應用於 Iron 軟體。

Iron Software 產品,如 IronOCR(光學字元辨識)和 IronPDF(PDF 生成),是利用 async 調用的完美候選。 將大型 HTML 文件轉換為 PDF 或掃瞄數百頁的圖片以尋找文字等作業通常都是綁定 CPU 的任務,或是涉及檔案系統 I/O,因此會從異步方法中獲益良多。

當您使用 Iron Software 提供的同步和異步方法時,可確保您的應用程式保持高度回應。

考慮使用 IronPDF 從指定的 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);
    });
}
$vbLabelText   $csharpLabel

使用異步方法產生 PDF

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;
}
$vbLabelText   $csharpLabel

這是一種標準模式,用來建立同時執行的任務,透過利用非阻塞的異步操作,大幅加快應用程式的回應時間。

2. 同步上下文和 ConfigureAwait(false)

當等待中的任務完成時,預設行為是擷取同步上下文,並確保繼續在相同的線程上(如 UI 線程)執行。 這對 UI 應用程式至關重要,但卻會在伺服器端或程式庫代碼中造成不必要的開銷。

使用 ConfigureAwait(false) 會告訴執行時,await 呼叫之後的程式碼可以在任何可用的線程池背景線程上繼續執行。 這是函式庫開發人員的重要作法,可確保異步操作達到最高效能:

// 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.
$vbLabelText   $csharpLabel

3.async void 的危險

異步程式設計中最重要的規則之一,就是除了異步事件處理器之外,絕對不要使用 async void。 例如,按鈕按一下事件處理方法通常會使用 async 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);
}
$vbLabelText   $csharpLabel

強烈不鼓勵使用任何其他的 async void 方法。 由於 async void 方法無法等待任務,因此呼叫線程無法追蹤其完成或可靠地處理異常,導致錯誤處理出現問題。 始終返回任務或任務對於所有其他非同步方法。

4.異常處理

強大的異常處理非常重要。 當異步操作失敗時(例如,網路服務呼叫遇到錯誤),異常會儲存在任務物件中。 當您等待任務時,await 表達式會將異常重新拋到目前的線程上(恢復延續的線程),讓標準的 try...catch 區塊能有效地用於異常處理。

結論

C# 中的 async 和 await 模式是一種範式轉換功能,可讓開發人員從脆弱的同步程式設計轉向彈性、可擴充的異步方法。 透過理解底層狀態機並遵循最佳實踐(例如,優先處理任務),可以提高效率。透過對 async void 進行處理,在庫中使用 ConfigureAwait(false),並正確實現異常處理——開發人員可以創建能夠以卓越的性能處理複雜處理任務(例如 Iron Software 套件中的任務)的應用程式。

Iron Software 致力於開發以高效能 async 程式設計為核心的產品,以確保您的程式碼撰寫實作能產生最大的吞吐量。 探索 Iron Software 的世界,看看利用異步任務處理如何大幅提升應用程式的速度和回應能力