Jak generować pliki PDF przy użyciu asynchroniczności i wielowątkowości

Jak generować pliki PDF za pomocą Async & Multithreading w C

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

IronPDF umożliwia wysokowydajną generację plików PDF w C# z użyciem operacji asynchronicznych i wielowątkowości, skracając czas przetwarzania wsadowego nawet o 65% w porównaniu z metodami synchronicznymi dla złożonych scenariuszy renderowania HTML.

Szybki start: Asynchroniczna konwersja HTML do PDF z IronPDF

Rozpocznij tworzenie asynchronicznej generacji PDF za pomocą IronPDF zaledwie w kilku linijkach kodu.

Za pomocą metody RenderHtmlAsPdfAsync można efektywnie przekonwertować zawartość HTML na PDF, optymalizując wydajność aplikacji. Ten przewodnik pokazuje, jak wykorzystać operacje asynchroniczne do wysokowydajnej generacji PDF, idealnej do przetwarzania wsadowego i w środowiskach wielowątkowych.

  1. Install IronPDF with NuGet Package Manager

    PM > Install-Package IronPdf
  2. Skopiuj i uruchom ten fragment kodu.

    var pdf = await IronPdf.ChromePdfRenderer.RenderHtmlAsPdfAsync("<h1>Hello World!</h1>");
  3. Wdrożenie do testowania w środowisku produkcyjnym

    Rozpocznij używanie IronPDF w swoim projekcie już dziś z darmową wersją próbną

    arrow pointer


Jak wdrożyć asynchroniczną generację PDF w C#?

IronPDF w pełni obsługuje operacje asynchroniczne, używając metod renderowania takich jak RenderHtmlAsPdfAsync. Asynchroniczna implementacja w IronPDF wykorzystuje asynchroniczny wzorzec oparty na zadaniach (TAP) do umożliwienia nieblokujących operacji generowania PDF. Takie podejście jest korzystne przy renderowaniu złożonych treści HTML lub przetwarzaniu równoczesnych żądań PDF. Dla pełnej dokumentacji metod, zobacz dokumentację metod renderowania.

Asynchroniczna generacja PDF zapobiega zamrażaniu interfejsu użytkownika w aplikacjach desktopowych i poprawia przepustowość żądań w aplikacjach internetowych. Wzorce używane w await pozwalają aplikacji obsługiwać inne operacje podczas oczekiwania na zakończenie renderowania PDF, znacznie zwiększając responsywność i doświadczenie użytkownika.

Dlaczego warto używać metod asynchronicznych do generacji PDF?

Metody asynchroniczne zapewniają kluczowe zalety dla przepływów pracy generacji PDF. Zapewniają one responsywność aplikacji podczas operacji wymagających dużej ilości zasobów, umożliwiają lepsze wykorzystanie zasobów na procesorach wielordzeniowych oraz poprawiają skalowalność w środowiskach serwerowych. Podczas przetwarzania złożonych konwersji HTML do PDF operacje asynchroniczne zapobiegają problemom z przekroczeniem limitu czasu i poprawiają komfort użytkowania.

: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);
Imports IronPdf
Imports System.Threading.Tasks

' Instantiate ChromePdfRenderer
Private renderer As New ChromePdfRenderer()

Private htmlStrings() As String = {"<h1>Html 1</h1>", "<h1>Html 2</h1>", "<h1>Html 3</h1>"}

' Create an array to store the tasks for rendering
Private renderingTasks = New Task(Of PdfDocument)(htmlStrings.Length - 1){}

For i As Integer = 0 To htmlStrings.Length - 1
	Dim index As Integer = i ' Capturing the loop variable
	renderingTasks(i) = Task.Run(Async Function()
		' Render HTML to PDF
		Return Await renderer.RenderHtmlAsPdfAsync(htmlStrings(index))
	End Function)
Next i

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

Jakie są typowe wzorce przetwarzania wsadowego?

Przetwarzanie plików PDF w trybie wsadowym wymaga starannego rozważenia kwestii wykorzystania pamięci i wydajności. Efektywne wzorce obejmują użycie Task.WhenAll do równoległego wykonywania wielu generacji PDF, wdrażanie wzorców producent-konsument z kanałami dla dużych partii i korzystanie z przykładów przetwarzania równoległego z dokumentacji 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;
}
Imports System.Collections.Generic
Imports System.Threading
Imports System.Threading.Tasks

' Batch processing with progress tracking
Public Async Function ProcessBatchAsync(htmlContents As List(Of String), progress As IProgress(Of Integer)) As Task(Of List(Of PdfDocument))
    Dim renderer As New ChromePdfRenderer()
    Dim results As New List(Of PdfDocument)()
    Dim completed As Integer = 0

    Dim tasks = htmlContents.Select(Async Function(html)
                                        Dim pdf = Await renderer.RenderHtmlAsPdfAsync(html)
                                        Interlocked.Increment(completed)
                                        progress?.Report(completed)
                                        Return pdf
                                    End Function)

    results.AddRange(Await Task.WhenAll(tasks))
    Return results
End Function
$vbLabelText   $csharpLabel

Jak radzić sobie z błędami w asynchronicznych operacjach na plikach PDF?

Obsługa błędów w asynchronicznych operacjach na plikach PDF wymaga kompleksowych strategii zarządzania wyjątkami. Użyj bloków catch w metodach asynchronicznych, wdrażaj logikę ponawiania dla tymczasowych awarii i rozważ użycie Polly do zaawansowanych polityk ponowienia. W celu szczegółowego rozwiązywania problemów związanych z wydajnością IronPDF zapewnia rozbudowane możliwości rejestrowania.

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");
}
Imports System
Imports System.Threading.Tasks

Public Class PdfRenderer
    Public Async Function RenderWithRetryAsync(html As String, Optional maxRetries As Integer = 3) As Task(Of PdfDocument)
        Dim renderer As New ChromePdfRenderer()

        For i As Integer = 0 To maxRetries - 1
            Try
                Return Await renderer.RenderHtmlAsPdfAsync(html)
            Catch ex As Exception When i < maxRetries - 1
                ' Log the exception
                Await Task.Delay(TimeSpan.FromSeconds(Math.Pow(2, i))) ' Exponential backoff
            End Try
        Next

        Throw New InvalidOperationException("Failed to render PDF after maximum retries")
    End Function
End Class
$vbLabelText   $csharpLabel
Icon Quote related to Jak radzić sobie z błędami w asynchronicznych operacjach na plikach PDF?

Moją ulubioną biblioteką tego typu jest IronPDF. Umożliwia ona szybkie i efektywne manipulowanie plikami PDF. Posiada także wiele cennych funkcji, takich jak eksport do formatu PDF/A i cyfrowe podpisywanie dokumentów PDF.

Milan Jovanovic related to Jak radzić sobie z błędami w asynchronicznych operacjach na plikach PDF?

Milan Jovanovic

Microsoft MVP

Zobacz studium przypadku
Icon Quote related to Jak radzić sobie z błędami w asynchronicznych operacjach na plikach PDF?

IronOCR pozwala nam oszczędzić 40 000 USD rocznie na ręcznym przetwarzaniu, jednocześnie zwiększając produktywność i uwalniając zasoby do zadań o wysokim wpływie. Gorąco polecam.

Brent Matzelle related to Jak radzić sobie z błędami w asynchronicznych operacjach na plikach PDF?

Brent Matzelle

Dyrektor technologiczny, OPYN

Zobacz studium przypadku
Icon Quote related to Jak radzić sobie z błędami w asynchronicznych operacjach na plikach PDF?

IronSuite odgrywa kluczową rolę w naszej działalności. Są to narzędzia zwiększające wydajność w całej firmie, w tym tworzenie planów pięter i poprawa zarządzania zapasami.

David Jones related to Jak radzić sobie z błędami w asynchronicznych operacjach na plikach PDF?

David Jones

Główny inżynier oprogramowania, Agorus Build

Zobacz studium przypadku

Jak mogę wykorzystać wielowątkowość do generowania plików PDF?

IronPDF jest bezpieczny w użyciu w środowiskach wielowątkowych i wspiera przetwarzanie wielowątkowe podczas korzystania z silnika renderującego ChromePdfRenderer. Należy pamiętać, że wielowątkowość jest ograniczona na maszynach macOS. Silnik renderujący Chrome zapewnia doskonałą bezpieczeństwo wątków i wydajność w przypadku operacji wykonywanych równolegle.

Wzorzec Parallel.ForEach sprawdza się dobrze w przetwarzaniu partii PDF, umożliwiając skuteczne wykorzystanie wszystkich dostępnych rdzeni CPU. Aby zapoznać się z wyczerpującymi przykładami generowania wielowątkowego, należy zapoznać się z dokumentacją IronPDF.

Kiedy należy wybrać wielowątkowość zamiast asynchroniczności?

Wielowątkowość jest idealnym rozwiązaniem w przypadku operacji obciążających procesor, gdzie konieczne jest jednoczesne przetwarzanie wielu plików PDF przy wystarczających zasobach systemowych. Wybierz wielowątkowość podczas przetwarzania dużych partii plików PDF na systemach wielordzeniowych, gdy generowanie każdego pliku PDF jest niezależne i gdy można kontrolować zużycie pamięci. Async jest lepszym rozwiązaniem w przypadku operacji ograniczonych przez operacje wejścia/wyjścia oraz w celu zachowania responsywności aplikacji.

Jakie są kwestie związane z bezpieczeństwem wątków?

ChromePdfRenderer IronPDF jest zaprojektowany jako bezpieczny w użyciu w środowiskach wielowątkowych, ale dotyczą go pewne ograniczenia. Twórz oddzielne instancje renderera dla każdego wątku podczas używania niestandardowych ustawień, unikaj współdzielenia instancji PdfDocument między wątkami bez synchronizacji oraz monitoruj zużycie pamięci podczas równoczesnego przetwarzania dużych dokumentów. Przegląd instalacji zawiera dodatkowe informacje na temat konfiguracji IronPDF w celu zapewnienia optymalnego bezpieczeństwa wątków.

// 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");
        });
}
Imports System
Imports System.Collections.Generic
Imports System.Threading
Imports System.Threading.Tasks
Imports IronPdf

' Thread-safe PDF generation with custom settings per thread
Public Sub ProcessPdfsInParallel(htmlContents As List(Of String))
    Parallel.ForEach(htmlContents, New ParallelOptions With {.MaxDegreeOfParallelism = Environment.ProcessorCount},
        Sub(html)
            ' Create a new renderer instance for each thread
            Dim renderer = New ChromePdfRenderer With {
                .RenderingOptions = New ChromePdfRenderOptions With {
                    .MarginTop = 10,
                    .MarginBottom = 10,
                    .PaperSize = IronPdf.Rendering.PdfPaperSize.A4
                }
            }

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

Ile wątków równoległych powinienem używać?

Optymalna liczba współbieżnych wątków zależy od rdzeni procesora, dostępnej pamięci i złożoności pliku PDF. Ogólne wytyczne obejmują używanie Environment.ProcessorCount dla operacji obciążających procesor, ograniczenie do 2-4 wątków dla PDFów o dużym zużyciu pamięci oraz monitorowanie zasobów systemowych w celu znalezienia optymalnej konfiguracji. Przykłady asynchroniczne ilustrują różne strategie wątkowania.

Jakich ulepszeń wydajności mogę się spodziewać?

Porównanie pokazuje znaczące różnice w wydajności między poszczególnymi metodami renderowania. Dodano 5-sekundowe opóźnienie w renderowaniu z klasą WaitFor dla symulacji skomplikowanego renderowania HTML. Poniżej znajduje się tabela porównawcza wydajności przy użyciu różnych technik opisanych powyżej.

Dlaczego asynchroniczność działa lepiej niż synchroniczność?

Normalne renderowanie Renderowanie asynchroniczne Renderowanie wielowątkowe
15,75 sekundy 05,59 sekundy 05,68 sekundy

Operacje asynchroniczne wyróżniają się, ponieważ umożliwiają efektywne zarządzanie zasobami puli wątków, zapobiegają blokowaniu głównego wątku i pozwalają na lepsze wykorzystanie procesora podczas operacji wejścia/wyjścia. Poprawa wydajności wynika z jednoczesnego uruchamiania wielu operacji renderowania zamiast czekania na sekwencyjne zakończenie każdej z nich.

Jak mogę zmierzyć wydajność mojej aplikacji?

Pomiar wydajności generowania plików PDF wymaga odpowiedniego testowania porównawczego i monitorowania. Użyj System.Diagnostics.Stopwatch do dokładnego pomiaru czasu, wdrażaj niestandardowe liczniki wydajności do monitorowania produkcji i wykorzystuj narzędzia typu application insights lub podobne APM. Warto rozważyć wykorzystanie przykładów z przewodnika szybkiego startu jako punktu odniesienia do testów wydajności.

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;
}
Imports System.Diagnostics
Imports System.Threading.Tasks

Public Class PerformanceMetrics
    ' Assume this class has an AddMeasurement method
    Public Sub AddMeasurement(milliseconds As Long)
        ' Implementation here
    End Sub
End Class

Public Class ChromePdfRenderer
    ' Assume this class has a RenderHtmlAsPdfAsync method
    Public Async Function RenderHtmlAsPdfAsync(html As String) As Task
        ' Implementation here
    End Function
End Class

Public Class PerformanceTester
    Public Async Function MeasurePerformanceAsync(html As String, iterations As Integer) As Task(Of PerformanceMetrics)
        Dim metrics As New PerformanceMetrics()
        Dim renderer As New ChromePdfRenderer()
        Dim stopwatch As New Stopwatch()

        ' Warm-up run
        Await renderer.RenderHtmlAsPdfAsync(html)

        For i As Integer = 0 To iterations - 1
            stopwatch.Restart()
            Await renderer.RenderHtmlAsPdfAsync(html)
            stopwatch.Stop()

            metrics.AddMeasurement(stopwatch.ElapsedMilliseconds)
        Next

        Return metrics
    End Function
End Class
$vbLabelText   $csharpLabel

Jakie czynniki wpływają na szybkość generowania plików PDF?

Na wydajność generowania plików PDF wpływa kilka czynników. Złożoność kodu HTML, w tym wykonywanie kodu JavaScript i renderowanie CSS, ma bezpośredni wpływ na czas przetwarzania. Ładowanie zasobów zewnętrznych, takich jak obrazy i czcionki, może powodować opóźnienia. Kluczową rolę odgrywają zasoby systemowe, takie jak procesor, pamięć i operacje wejścia/wyjścia na dysku. Na szybkość ma również wpływ konfiguracja IronPDF, w tym opcje renderowania i ustawienia silnika. Zrozumienie tych czynników pomaga zoptymalizować proces generowania plików PDF w celu uzyskania maksymalnej wydajności.

W przypadku złożonych scenariuszy wymagających intensywnego wykorzystania JavaScriptu lub opóźnionego renderowania warto rozważyć użycie mechanizmów WaitFor, aby zapewnić pełne wyrenderowanie strony przed wygenerowaniem pliku PDF. Takie podejście gwarantuje dokładny wynik przy zachowaniu przewidywalnych parametrów wydajności.

Często Zadawane Pytania

Ile poprawy wydajności mogę oczekiwać przy asynchronicznym generowaniu PDF?

Asynchroniczne operacje i wielowątkowość IronPDF mogą skrócić czas przetwarzania wsadowego do 65% w porównaniu do metod synchronicznych, zwłaszcza podczas renderowania złożonych treści HTML. Faktyczny zysk wydajności zależy od czynników takich jak złożoność HTML, zasoby systemowe i liczba równoczesnych operacji.

Jaki jest najprostszy sposób na asynchroniczną konwersję HTML do PDF?

Najprostszy sposób to użycie metody RenderHtmlAsPdfAsync IronPDF. Za pomocą jednego wiersza kodu: `var pdf = await IronPdf.ChromePdfRenderer.RenderHtmlAsPdfAsync("Hello World!");`, możesz efektywnie konwertować zawartość HTML na PDF, zachowując responsywność aplikacji.

Dlaczego powinienem używać metod asynchronicznych zamiast synchronicznego generowania PDF?

Metody asynchroniczne w IronPDF zapobiegają zamarzaniu interfejsu użytkownika w aplikacjach desktopowych, poprawiają przepustowość żądań w aplikacjach internetowych, umożliwiają lepsze wykorzystanie zasobów w procesorach wielordzeniowych oraz zwiększają skalowalność w środowiskach serwerowych. Są szczególnie korzystne podczas obsługi złożonych konwersji HTML do PDF lub przetwarzania wielu żądań PDF jednocześnie.

Jakiego wzorca asynchronicznego biblioteka używa do operacji PDF?

IronPDF wdraża wzorzec asynchroniczny oparty na zadaniach (TAP) dla swoich operacji asynchronicznych, w tym metody takie jak RenderHtmlAsPdfAsync. Wzorzec ten umożliwia nieblokujące operacje generowania PDF i integruje się bezproblemowo z asynchronicznymi słowami kluczowymi C#.

Jak mogę przetwarzać wiele plików PDF równolegle dla lepszej wydajności?

IronPDF obsługuje przetwarzanie wsadowe za pomocą wzorców takich jak Task.WhenAll do równoległego wykonywania wielu generacji PDF, Parallel.ForEach do wielowątkowości w przetwarzaniu PDF oraz wzorców producent-konsument z kanałami do dużych partii. Te podejścia optymalizują wykorzystanie zasobów i znacząco skracają całkowity czas przetwarzania.

Chipego
Inżynier oprogramowania
Chipego ma naturalną umiejętność słuchania, która pomaga mu zrozumieć problemy klientów i oferować inteligentne rozwiązania. Dołączył do zespołu Iron Software w 2023 roku, po ukończeniu licencjatu z technologii informatycznej. IronPDF i IronOCR to dwa produkty, na których Chipego się skupia, ale jego ...
Czytaj więcej
Gotowy, aby rozpocząć?
Nuget Pliki do pobrania 19,936,792 | Wersja: 2026.7 właśnie wydany
Still Scrolling Icon

Wciąż przewijasz?

Czy chcesz szybko dowodu? PM > Install-Package IronPdf
Uruchom przykład i zobacz, jak Twój kod HTML zamienia się w plik PDF.