如何生成非同步和多线程 PDF 文件

如何在 C# 中使用非同步和多執行緒產生 PDF

This article was translated from English: Does it need improvement?
Translated
View the article in English

IronPDF使用非同步操作和多執行緒在 C# 中實現高效能 PDF 生成,與複雜的 HTML 渲染場景的同步方法相比,可將批次處理時間縮短高達 65%。

快速入門:使用IronPDF非同步將 HTML 轉換為 PDF

只需幾行程式碼,即可使用IronPDF開始非同步產生 PDF。

使用 RenderHtmlAsPdfAsync 方法,您可以有效地將 HTML 內容轉換為 PDF,從而優化應用程式的效能。 本指南展示如何利用非同步操作產生高效能 PDF,非常適合批次處理和多執行緒環境。

  1. 使用NuGet套件管理器安裝https://www.nuget.org/packages/IronPdf

    PM > Install-Package IronPdf
  2. 複製並運行這段程式碼。

    var pdf = await IronPdf.ChromePdfRenderer.RenderHtmlAsPdfAsync("<h1>Hello World!</h1>");
  3. 部署到您的生產環境進行測試

    今天就在您的專案中開始使用免費試用IronPDF

    arrow pointer


如何在C#中實現異步PDF生成?

IronPDF完全支援使用渲染方法的非同步操作,例如 RenderHtmlAsPdfAsyncIronPDF中的非同步實作利用了基於任務的非同步模式 (TAP) 來實現非阻塞 PDF 生成操作。 這種方法有利於複雜的HTML內容渲染或同時處理PDF請求。

非同步 PDF 產生可防止桌面應用程式中的 UI 卡頓,並提高 Web 應用程式中的請求吞吐量。 使用 await 模式可讓您的應用程式在等待 PDF 渲染完成時處理其他操作,從而顯著提高響應速度和使用者體驗。

為什麼生成 PDF 檔案時應該使用非同步方法?

非同步方法為 PDF 生成工作流程提供了關鍵優勢。 它們在資源密集型操作期間保持應用程式的回應能力,在多核心處理器上實現更好的資源利用率,並提高伺服器環境的可擴展性。 在處理複雜的 HTML 到 PDF 轉換時,非同步操作可以防止逾時問題並改善使用者體驗。

:path=/static-assets/pdf/content-code-examples/how-to/async-async.cs
using IronPdf;
using System.Threading.Tasks;

// Instantiate ChromePdfRenderer
ChromePdfRenderer renderer = new ChromePdfRenderer();

string[] htmlStrings = {"<h1>Html 1</h1>", "<h1>Html 2</h1>", "<h1>Html 3</h1>"};

// Create an array to store the tasks for rendering
var renderingTasks = new Task<PdfDocument>[htmlStrings.Length];

for (int i = 0; i < htmlStrings.Length; i++)
{
    int index = i; // Capturing the loop variable
    renderingTasks[i] = Task.Run(async () =>
    {
        // Render HTML to PDF
        return await renderer.RenderHtmlAsPdfAsync(htmlStrings[index]);
    });
}

// Wait for all rendering tasks to complete
// await Task.WhenAll(renderingTasks);
$vbLabelText   $csharpLabel

批量處理的常見模式有哪些?

批次處理 PDF 檔案需要仔細考慮記憶體使用和效能。 有效的模式包括使用 Task.WhenAll 並行執行多個 PDF 生成,使用通道實現生產者-消費者模式以處理大批量數據,以及利用IronPDF文檔中的平行處理範例

// Batch processing with progress tracking
public async Task<List<PdfDocument>> ProcessBatchAsync(List<string> htmlContents, IProgress<int> progress)
{
    var renderer = new ChromePdfRenderer();
    var results = new List<PdfDocument>();
    var completed = 0;

    var tasks = htmlContents.Select(async html => {
        var pdf = await renderer.RenderHtmlAsPdfAsync(html);
        Interlocked.Increment(ref completed);
        progress?.Report(completed);
        return pdf;
    });

    results.AddRange(await Task.WhenAll(tasks));
    return results;
}
// Batch processing with progress tracking
public async Task<List<PdfDocument>> ProcessBatchAsync(List<string> htmlContents, IProgress<int> progress)
{
    var renderer = new ChromePdfRenderer();
    var results = new List<PdfDocument>();
    var completed = 0;

    var tasks = htmlContents.Select(async html => {
        var pdf = await renderer.RenderHtmlAsPdfAsync(html);
        Interlocked.Increment(ref completed);
        progress?.Report(completed);
        return pdf;
    });

    results.AddRange(await Task.WhenAll(tasks));
    return results;
}
$vbLabelText   $csharpLabel

如何處理非同步 PDF 操作中的錯誤?

非同步 PDF 操作中的錯誤處理需要全面的異常管理策略。 在非同步方法中使用 try-catch 區塊,為瞬態故障實作重試邏輯,並考慮使用 Polly 來實現高階重試策略。 IronPDF提供強大的日誌記錄功能,可用於詳細檢查效能問題

public async Task<PdfDocument> RenderWithRetryAsync(string html, int maxRetries = 3)
{
    var renderer = new ChromePdfRenderer();

    for (int i = 0; i < maxRetries; i++)
    {
        try
        {
            return await renderer.RenderHtmlAsPdfAsync(html);
        }
        catch (Exception ex) when (i < maxRetries - 1)
        {
            // Log the exception
            await Task.Delay(TimeSpan.FromSeconds(Math.Pow(2, i))); // Exponential backoff
        }
    }

    throw new InvalidOperationException("Failed to render PDF after maximum retries");
}
public async Task<PdfDocument> RenderWithRetryAsync(string html, int maxRetries = 3)
{
    var renderer = new ChromePdfRenderer();

    for (int i = 0; i < maxRetries; i++)
    {
        try
        {
            return await renderer.RenderHtmlAsPdfAsync(html);
        }
        catch (Exception ex) when (i < maxRetries - 1)
        {
            // Log the exception
            await Task.Delay(TimeSpan.FromSeconds(Math.Pow(2, i))); // Exponential backoff
        }
    }

    throw new InvalidOperationException("Failed to render PDF after maximum retries");
}
$vbLabelText   $csharpLabel

如何使用多執行緒產生 PDF 檔案?

IronPDF是線程安全的,並且在使用 ChromePdfRenderer 渲染引擎時支援多執行緒。請注意,在 macOS 系統上,多執行緒功能受到限制。 Chrome渲染引擎為並發操作提供了絕佳的執行緒安全性和效能特性。

The Parallel.ForEach pattern works well for batch processing PDFs, allowing you to leverage all available CPU cores effectively. 有關全面的多線程生成範例,請參閱IronPDF文件。

何時應該選擇多執行緒而不是異步?

多執行緒非常適合 CPU 密集型操作,例如需要同時處理多個 PDF 檔案且需要充足系統資源的情況。 在多核心系統上處理大量 PDF 檔案、每次 PDF 產生都是獨立的、並且可以控制記憶體使用量時,請選擇多執行緒。 非同步操作更適合 I/O 密集型操作,並能維持應用程式的回應速度。

螺紋安全需要考慮哪些因素?

IronPDF 的 ChromePdfRenderer 設計為線程安全,但仍需注意某些事項。 使用自訂設定時,為每個執行緒建立單獨的渲染器實例;避免在執行緒之間共用 PdfDocument 實例而不進行同步;並監控並發處理大型文件時的記憶體消耗。 安裝概述提供了有關配置IronPDF以獲得最佳線程安全性的更多詳細資訊。

// Thread-safe PDF generation with custom settings per thread
public void ProcessPdfsInParallel(List<string> htmlContents)
{
    Parallel.ForEach(htmlContents, new ParallelOptions { MaxDegreeOfParallelism = Environment.ProcessorCount }, 
        html =>
        {
            // Create a new renderer instance for each thread
            var renderer = new ChromePdfRenderer
            {
                RenderingOptions = new ChromePdfRenderOptions
                {
                    MarginTop = 10,
                    MarginBottom = 10,
                    PaperSize = IronPdf.Rendering.PdfPaperSize.A4
                }
            };

            var pdf = renderer.RenderHtmlAsPdf(html);
            pdf.SaveAs($"output_{Thread.CurrentThread.ManagedThreadId}_{DateTime.Now.Ticks}.pdf");
        });
}
// Thread-safe PDF generation with custom settings per thread
public void ProcessPdfsInParallel(List<string> htmlContents)
{
    Parallel.ForEach(htmlContents, new ParallelOptions { MaxDegreeOfParallelism = Environment.ProcessorCount }, 
        html =>
        {
            // Create a new renderer instance for each thread
            var renderer = new ChromePdfRenderer
            {
                RenderingOptions = new ChromePdfRenderOptions
                {
                    MarginTop = 10,
                    MarginBottom = 10,
                    PaperSize = IronPdf.Rendering.PdfPaperSize.A4
                }
            };

            var pdf = renderer.RenderHtmlAsPdf(html);
            pdf.SaveAs($"output_{Thread.CurrentThread.ManagedThreadId}_{DateTime.Now.Ticks}.pdf");
        });
}
$vbLabelText   $csharpLabel

我應該使用多少個並發線程?

最佳並發執行緒數取決於 CPU 核心數、可用記憶體和 PDF 複雜度。 一般準則包括:對 CPU 密集型操作使用 Environment.ProcessorCount,對記憶體密集型 PDF 限制為 2-4 個線程,以及監控系統資源以找到最佳配置。 非同步範例演示了各種線程策略。

性能方面可以期待哪些提升?

比較結果顯示,不同渲染方法之間存在顯著的效能差異。 使用WaitFor 類別在渲染時添加 5 秒延遲,以模擬複雜的 HTML 渲染。 下面表格比較了使用上述各種技術時的表現。

為什麼非同步程式設計比同步程式設計效能更好?

普通渲染 非同步渲染 多線程渲染
15.75秒 5.59秒 5.68秒

非同步操作的優點在於能夠有效管理執行緒池資源,防止主執行緒阻塞,並在 I/O 操作期間更好地利用 CPU。 效能提升來自於同時啟動多個渲染操作,而不是等待每個操作按順序完成。

如何衡量應用程式的效能?

衡量 PDF 生成效能需要進行適當的基準測試和監控。 使用 System.Diagnostics.Stopwatch 進行精確的時間測量,實現自訂效能計數器以進行生產監控,並利用應用程式洞察或類似的 APM 工具。 可以考慮使用快速入門指南中的範例作為效能測試的基準。

public async Task<PerformanceMetrics> MeasurePerformanceAsync(string html, int iterations)
{
    var metrics = new PerformanceMetrics();
    var renderer = new ChromePdfRenderer();
    var stopwatch = new Stopwatch();

    // Warm-up run
    await renderer.RenderHtmlAsPdfAsync(html);

    for (int i = 0; i < iterations; i++)
    {
        stopwatch.Restart();
        await renderer.RenderHtmlAsPdfAsync(html);
        stopwatch.Stop();

        metrics.AddMeasurement(stopwatch.ElapsedMilliseconds);
    }

    return metrics;
}
public async Task<PerformanceMetrics> MeasurePerformanceAsync(string html, int iterations)
{
    var metrics = new PerformanceMetrics();
    var renderer = new ChromePdfRenderer();
    var stopwatch = new Stopwatch();

    // Warm-up run
    await renderer.RenderHtmlAsPdfAsync(html);

    for (int i = 0; i < iterations; i++)
    {
        stopwatch.Restart();
        await renderer.RenderHtmlAsPdfAsync(html);
        stopwatch.Stop();

        metrics.AddMeasurement(stopwatch.ElapsedMilliseconds);
    }

    return metrics;
}
$vbLabelText   $csharpLabel

哪些因素會影響PDF生成速度?

影響PDF生成性能的因素有很多。 HTML 的複雜性,包括JavaScript執行和 CSS 渲染,會直接影響處理時間。外部資源加載,例如圖片和字體,也會引入延遲。 CPU、記憶體和磁碟 I/O 等系統資源發揮著至關重要的作用。 IronPDF 的配置,包括渲染選項和引擎設置,也會影響速度。 了解這些因素有助於優化您的 PDF 生成工作流程,從而最大限度地提高效率。

對於涉及大量JavaScript或延遲渲染的複雜場景,請考慮使用WaitFor 機制來確保在產生 PDF 之前完成頁面渲染。 這種方法既能保證輸出準確,又能維持可預測的性能特性。

常見問題解答

使用 async PDF 生成,性能可以提高多少?

與同步處理方法相比,IronPDF 的異步操作和多執行緒可減少高達 65% 的批次處理時間,尤其是在渲染複雜的 HTML 內容時。實際的效能增益取決於 HTML 複雜度、系統資源以及並發作業的數量等因素。

將 HTML 非同步轉換為 PDF 的最簡單方法是什麼?

最簡單的方法是使用 IronPDF 的 RenderHtmlAsPdfAsync 方法。只需一行代碼`var pdf = await IronPdf.ChromePdfRenderer.RenderHtmlAsPdfAsync("Hello World!");`,您就可以高效地將 HTML 內容轉換為 PDF,同時保持應用程式的回應能力。

為何要使用 async 方法而非同步 PDF 產生?

IronPDF 中的 Async 方法可以防止桌面應用程式中的 UI 凍結、提高 Web 應用程式中的請求吞吐量、在多核心處理器上實現更好的資源利用率,以及增強伺服器環境中的可擴展性。在處理複雜的 HTML 至 PDF 轉換或同時處理多個 PDF 請求時,它們尤其有用。

該函式庫使用何種 async 模式進行 PDF 作業?

IronPDF 在其異步操作中實現了基於任務的異步模式 (TAP),包括 RenderHtmlAsPdfAsync 等方法。此模式可實現非阻塞 PDF 生成作業,並與 C# 的 async/await 關鍵字無縫整合。

如何並行處理多個 PDF 以獲得更好的效能?

IronPDF 支援使用 Task.WhenAll 等模式進行批次處理,以平行執行多個 PDF 世代;Parallel.ForEach 可在 PDF 處理中執行多執行緒;而生產者-消費者模式則可使用通道進行大量批次處理。這些方法可最佳化資源使用,並大幅縮短總處理時間。

Chipego
軟體工程師
Chipego 擁有自然的傾聽技巧,這有助於他理解客戶問題並提供智能解決方案。他於 2023 年加入 Iron Software 團隊,擁有信息技術學士學位。IronPDF 和 IronOCR 是 Chipego 專注的兩個產品,但他對所有產品的知識日漸增長,因為他發現新的方法來支持客戶。他喜歡 Iron Software 的合作生活,來自公司的成員將他們的各種經驗帶來貢獻於有效及創新解決方案。當 Chipego 離開書桌時,他經常被発現正享受一本好書或者在踢足球。
準備好開始了嗎?
Nuget 下載 17,803,474 | 版本: 2026.3 剛剛發布
Still Scrolling Icon

還在滾動嗎?

想快速取得證據? PM > Install-Package IronPdf
運行範例看著你的HTML程式碼變成PDF檔。