DIE IRON SUITE VERWENDEN

Mastering Async/Await C# in .NET 10: Das grundlegende Handbuch für skalierbare Anwendungen

Asynchron/Erwarten C#

Die moderne Softwareentwicklung erfordert Schnelligkeit, Reaktionsfähigkeit und unvergleichliche Skalierbarkeit. In der Welt der Webanwendungen und Unternehmenslösungen ist es einfach inakzeptabel, den UI-Thread zu blockieren oder Serverressourcen zu beanspruchen. Hier wird asynchrones Programmieren, angetrieben durch die mächtigen async und await Schlüsselwörter in C#, nicht nur zu einem Feature, sondern zu einem obligatorischen architektonischen Fundament.

Für Entwickler, die leistungsstarke Bibliotheken wie die Iron Software Suite für PDF-Generierung, Bildbearbeitung und OCR nutzen, ist das Verständnis dafür, wie man asynchronen Code schreibt, entscheidend, um effizienten Code zu erstellen, der die volle Leistung der .NET Task Parallel Library ausschöpft.

Wir werden tief in die Mechanik von async/await C# eintauchen, um zu erforschen, wie dieser Paradigmenwechsel langsame synchrone Programmierung in hochdurchsatzfähige asynchrone Operationen verwandelt, und diese kritischen Konzepte aufzeigen, wie Iron Software Unternehmen hilft, maximale Leistung zu erzielen.

Die Grundlagen der asynchronen Programmierung

Vor async und await wurden asynchrone Operationen durch umständliche Callbacks und manuelle Operationen der Task-Klasse verwaltet, was zu komplexem und fehleranfälligem Code führte. Asynchrones Programmieren in C# hat dies vereinfacht, indem es Entwicklern ermöglicht, Code zu schreiben, der wie synchroner Code aussieht, sich aber asynchron verhält.

Die beiden Kernkomponenten sind:

  1. Das async-Schlüsselwort: Der async-Modifikator kennzeichnet eine Methode als async-Methode, die await-Ausdrücke enthalten kann. Entscheidend ist, dass die Kennzeichnung einer Methode als asynchron nicht automatisch bedeutet, dass sie in einem Hintergrund-Thread ausgeführt wird. Es ermöglicht dem Compiler lediglich, eine ausgeklügelte Zustandsmaschine zu generieren, die die Fortsetzung des Codes verwaltet. Eine asynchrone Methode gibt im Allgemeinen ein Task-Objekt (Task oder Task) zurück, um die laufende asynchrone Aufgabe darzustellen.

  2. Das Schlüsselwort await: Das Schlüsselwort await ist die magische Komponente. Wenn ein await-Ausdruck auftritt, prüft die Methode, ob die erwartete Aufgabe abgeschlossen ist. Wenn dies nicht der Fall ist, pausiert die Methode sofort die Ausführung und gibt die Kontrolle an die aufrufende Methode (oder den Aufrufer) zurück. Dadurch wird der aktuelle Thread (oft der Hauptthread oder ein Thread-Pool-Thread) freigegeben, um andere Anfragen oder Aufgaben zu bearbeiten. Wenn die Aufgabe abgeschlossen ist, wird der Rest der Methode als Fortsetzung registriert und für die Ausführung neu geplant.

Hier ist ein grundlegendes Code-Beispiel:

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

Die Verwendung der statischen asynchronen Aufgabe main ist der moderne Standard, der es überflüssig macht, den Haupt-Thread mit Legacy-Methoden wie .Wait() oder .Result zu blockieren.

Performance und Iron Software Integration

Während Task der Standardrückgabetyp für asynchronen Code ist, verwendet fortgeschrittene asynchrone Programmierung in .NET 10 oft ValueTask, um beträchtliche Leistungssteigerungen in "Hot Paths" zu erzielen, in denen eine synchrone Fertigstellung wahrscheinlich ist (z.B. das Abrufen eines zwischengespeicherten Werts). ValueTask vermeidet Speicherzuweisungen und ist daher für Anwendungen mit hohem Durchsatz von entscheidender Bedeutung.

Anwendung asynchroner Operationen auf Iron Software

Iron Software Produkte wie IronOCR (Optische Zeichenerkennung) und IronPDF (PDF-Erstellung) sind perfekte Kandidaten, um von asynchronen Aufrufen zu profitieren. Operationen wie das Konvertieren eines großen HTML-Dokuments in ein PDF oder das Scannen von Hunderten von Seitenbildern auf Text sind häufig CPU-gebundene Aufgaben oder beinhalten Dateisystem-I/O, die enorm von asynchronen Methoden profitieren.

Wenn Sie die von Iron Software bereitgestellten synchronen und asynchronen Methoden verwenden, stellen Sie sicher, dass Ihre Anwendung in hohem Maße reaktionsfähig bleibt.

Betrachten Sie die Verwendung von IronPDF, um ein Dokument aus einer angegebenen URL zu erstellen:

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

PDF mit Async-Methoden generiert

PDF asynchron gerendert

Durch die Verwendung der asynchronen Methode RenderHtmlAsPdfAsync() verhindern wir, dass die Anwendung bei der Verarbeitung großer Dokumente einfriert oder blockiert. Es wird gezeigt, wie man asynchronen Code für komplexe Verarbeitungen effizient schreibt.

Beste Praktiken und Grenzfälle

1. die Handhabung mehrerer Tasks und E/A

Um die Effizienz zu maximieren, sollten Sie mehrere Aufgaben gleichzeitig starten, wenn Sie auf unabhängige E/A-gebundene Arbeiten warten, wie z. B. das Abrufen von Daten von einem Remote-Server oder die Durchführung von Datenbankabfragen.

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

Dies ist ein Standardmuster für die Erstellung von Aufgaben, die gleichzeitig ausgeführt werden und die Reaktionszeiten von Anwendungen durch die Verwendung von nicht blockierenden asynchronen Operationen drastisch beschleunigen.

2. der Synchronisationskontext und ConfigureAwait(false)

Wenn eine erwartete Aufgabe abgeschlossen wird, besteht das Standardverhalten darin, den Synchronisierungskontext zu erfassen und sicherzustellen, dass die Fortsetzung auf demselben Thread (wie dem UI-Thread) ausgeführt wird. Dies ist für UI-Anwendungen von entscheidender Bedeutung, verursacht aber unnötigen Overhead in serverseitigem oder Bibliothekscode.

Die Verwendung von ConfigureAwait(false) teilt der Laufzeitumgebung mit, dass der Code nach dem await-Aufruf auf allen verfügbaren Threadpool-Hintergrundthreads fortgesetzt werden kann. Dies ist ein wichtiges Verfahren für Bibliotheksentwickler, um maximale Leistung für asynchrone Operationen zu gewährleisten:

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

3. die Gefahr von async void

Eine der wichtigsten Regeln bei der asynchronen Programmierung ist es, async void nur für asynchrone Event-Handler zu verwenden. Zum Beispiel wird eine Methode zur Behandlung von Schaltflächenklicks typischerweise async void verwenden:

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

Von jeder anderen Verwendung von asynchronen ungültigen Methoden wird dringend abgeraten. Da eine async void-Methode nicht erwartet werden kann, kann der aufrufende Thread ihre Fertigstellung nicht verfolgen oder zuverlässig Ausnahmen behandeln, was die Fehlerbehandlung problematisch macht. Geben Sie für alle anderen asynchronen Methoden immer Task oder Task zurück.

4. die Behandlung von Ausnahmen

Eine solide Ausnahmebehandlung ist unerlässlich. Wenn ein asynchroner Vorgang fehlschlägt (z. B. wenn ein Webdienstaufruf auf einen Fehler stößt), wird die Ausnahme im Task-Objekt gespeichert. Wenn Sie die Aufgabe abwarten, wirft der await-Ausdruck die Ausnahme auf den aktuellen Thread (denjenigen, der die Fortsetzung fortsetzt), so dass standardmäßige try...catch-Blöcke effektiv für die Ausnahmebehandlung eingesetzt werden können.

Abschluss

Das async- und await-Muster in C# ist ein Paradigmenwechsel, der Entwickler weg von der spröden synchronen Programmierung hin zu belastbaren, skalierbaren asynchronen Methoden bringt. Durch das Verständnis der zugrundeliegenden Zustandsmaschine und das Einhalten von Best Practices - wie der Priorisierung von Task über async void, der Verwendung von ConfigureAwait(false) in Bibliotheken und der korrekten Implementierung der Ausnahmebehandlung - können Entwickler Anwendungen erstellen, die komplexe Verarbeitungsvorgänge (wie die in der Iron Software-Suite) mit außergewöhnlicher Leistung bewältigen.

Iron Software hat sich der Entwicklung von Produkten verschrieben, deren Kernstück die asynchrone Hochleistungsprogrammierung ist, um sicherzustellen, dass Sie beim Schreiben von Code einen maximalen Durchsatz erzielen. Entdecken Sie die Welt von Iron Software und sehen Sie, wie die Nutzung der asynchronen Aufgabenverarbeitung die Geschwindigkeit und Reaktionsfähigkeit Ihrer Anwendung dramatisch verbessern kann.