Zum Fußzeileninhalt springen
.NET HILFE

C# ConcurrentDictionary (Wie es für Entwickler funktioniert)

Wenn Sie mit multithreaded Anwendungen in C# arbeiten, ist die Aufrechterhaltung der Datenintegrität entscheidend, insbesondere wenn Sie PDF-Dokumente mit einer Bibliothek wie IronPDF dynamisch generieren. Die Klasse ConcurrentDictionary<tkey, tvalue> bietet eine threadsichere Sammlung zur effizienten Verwaltung von Schlüssel-Wert-Paaren, selbst wenn mehrere Threads gleichzeitig Operationen wie Einfügungen, Aktualisierungen oder Suchvorgänge durchführen.

In diesem Leitfaden werden wir untersuchen, wie ConcurrentDictionary funktioniert, wie es sich in IronPDF für parallele PDF-Verarbeitung integrieren lässt und was jeder .NET-Entwickler über Schlüsseltypen, Threadsicherheit und häufige Fallstricke wie die Behandlung eines vorhandenen Schlüssels oder die Sicherstellung von Datenkonsistenz wissen muss.

Was ist ein ConcurrentDictionary in C#?

Die Klasse ConcurrentDictionary<tkey, tvalue>, Teil des System.Collections.Concurrent-Namespace, ist eine generische Sammlung, die für hochleistungsfähige, threadsichere Operationen entwickelt wurde. Im Gegensatz zu einem regulären Wörterbuch können mehrere Threads die Sammlung sicher zugreifen und ändern, ohne die gesamte Struktur zu sperren.

Eine neue Instanz von ConcurrentDictionary<string, string> könnte folgendermaßen aussehen:

var dictionary = new ConcurrentDictionary<string, string>();
var dictionary = new ConcurrentDictionary<string, string>();
Dim dictionary = New ConcurrentDictionary(Of String, String)()
$vbLabelText   $csharpLabel

Sie können Ihre eigenen TKey- und TValue-Typen basierend auf Ihrem spezifischen Anwendungsfall definieren, z. B. zum Zwischenspeichern gerenderter PDF-Dateipfade oder zum Verfolgen gleichzeitiger PDF-Generierungsaufgaben.

Warum ConcurrentDictionary mit IronPDF verwenden?

Stellen Sie sich vor, Sie erstellen ein Programm, das personalisierte Rechnungen mit IronPDF für Tausende von Benutzern generiert. Wenn jeder Thread ein Dokument rendern und dessen Ergebnis speichern muss, würde ein reguläres Wörterbuch zu Wettlaufsituationen führen oder Ausnahmen auslösen, wenn ein Schlüssel bereits existiert.

Die Verwendung von ConcurrentDictionary stellt sicher:

  • Datenkonsistenz über Threads hinweg
  • Effiziente Lese- und Schreibvorgänge
  • Vermeidung unbekannter Programmfehler
  • Null-Sperrungs-Overhead, wenn mehrere Threads auf verschiedene Schlüssel zugreifen

Gängige Methoden und ihre Verwendung mit IronPDF

Lassen Sie uns die wichtigsten Methoden anhand von IronPDF-Rendering-Szenarien aufschlüsseln.

GetOrAdd-Methode: Abrufen oder Hinzufügen eines neuen Schlüssels

Diese Methode prüft, ob ein bestimmter Schlüssel vorhanden ist. Falls nicht, wird der neue Wert hinzugefügt.

var filePath = pdfCache.GetOrAdd(userId, id => GeneratePdfForUser(id));
var filePath = pdfCache.GetOrAdd(userId, id => GeneratePdfForUser(id));
Dim filePath = pdfCache.GetOrAdd(userId, Function(id) GeneratePdfForUser(id))
$vbLabelText   $csharpLabel
  • Gewährleistet Threadsicherheit
  • Vermeidet doppeltes Rendering
  • Gibt den zugehörigen Wert für den angegebenen Schlüssel zurück

AddOrUpdate Methode: Bestehende Werte elegant behandeln

Diese Methode ermöglicht es Ihnen, den Wert zu aktualisieren, wenn der Schlüssel existiert, oder ein neues Schlüsselwertpaar hinzuzufügen.

pdfCache.AddOrUpdate(userId,
    id => GeneratePdfForUser(id),
    (id, existingValue) => UpdatePdfForUser(id, existingValue));
pdfCache.AddOrUpdate(userId,
    id => GeneratePdfForUser(id),
    (id, existingValue) => UpdatePdfForUser(id, existingValue));
pdfCache.AddOrUpdate(userId, Function(id) GeneratePdfForUser(id), Function(id, existingValue) UpdatePdfForUser(id, existingValue))
$vbLabelText   $csharpLabel
  • Verwaltet Logik für vorhandenen Schlüssel
  • Gewährleistet, dass auf Mitglieder sicher zugegriffen wird, während gleichzeitiger Zugriff besteht

TryAdd-Methode: Hinzufügen, wenn der Schlüssel nicht vorhanden ist

Diese Methode versucht, einen Wert hinzuzufügen und gibt einen booleschen Wert zurück, der den Erfolg anzeigt.

bool added = pdfCache.TryAdd(userId, pdfBytes);
if (!added)
{
    Console.WriteLine("PDF already cached.");
}
bool added = pdfCache.TryAdd(userId, pdfBytes);
if (!added)
{
    Console.WriteLine("PDF already cached.");
}
Dim added As Boolean = pdfCache.TryAdd(userId, pdfBytes)
If Not added Then
	Console.WriteLine("PDF already cached.")
End If
$vbLabelText   $csharpLabel
  • Perfekt, um Konflikte zu vermeiden
  • Methode gibt true zurück, wenn das Einfügen erfolgreich ist

Benutzungsfall-Tabelle: ConcurrentDictionary-Methoden

C# Concurrentdictionary (Wie es für Entwickler funktioniert): Abbildung 1 - Anwendungsfalltabelle

Optimierung für Leistung

ConcurrentDictionary unterstützt Tuning über den Konstruktor:

int concurrencyLevel = 4;
int initialCapacity = 100;
var dictionary = new ConcurrentDictionary<string, byte[]>(concurrencyLevel, initialCapacity);
int concurrencyLevel = 4;
int initialCapacity = 100;
var dictionary = new ConcurrentDictionary<string, byte[]>(concurrencyLevel, initialCapacity);
Dim concurrencyLevel As Integer = 4
Dim initialCapacity As Integer = 100
Dim dictionary = New ConcurrentDictionary(Of String, Byte())(concurrencyLevel, initialCapacity)
$vbLabelText   $csharpLabel
  • concurrencyLevel: Erwartete Anzahl von Threads (Standard = Standardeinstellung der Konnurrenzebene)
  • initialCapacity: Erwartete Anzahl an Elementen (Standardanfangskapazität)

Durch richtiges Setzen dieser Werte wird der Durchsatz verbessert und Verdrängung über mehrere Threads hinweg reduziert.

Vermeidung von Problemen mit Schlüsselkonflikten und Standardwerten

Wenn ein Schlüssel nicht existiert, können Operationen wie TryGetValue den Standardwert des Typs zurückgeben:

if (!pdfCache.TryGetValue(userId, out var pdf))
{
    pdf = GeneratePdfForUser(userId); // Second call
}
if (!pdfCache.TryGetValue(userId, out var pdf))
{
    pdf = GeneratePdfForUser(userId); // Second call
}
Dim pdf As var
If Not pdfCache.TryGetValue(userId, pdf) Then
	pdf = GeneratePdfForUser(userId) ' Second call
End If
$vbLabelText   $csharpLabel

Dies schützt Ihren Code vor unbekanntem Code oder Nullverweisen. Überprüfen Sie immer auf einen bestimmten Wert, bevor Sie die Anwesenheit annehmen.

Praktisches Beispiel: Thread-sicherer IronPDF Report Generator

using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
using IronPdf;
public class Program
{
    static ConcurrentDictionary<string, byte[]> pdfReports =
        new ConcurrentDictionary<string, byte[]>();
    static void Main(string[] args)
    {
        // Simulated user list with HTML content
        var users = new List<User>
        {
            new User { Id = "user1", HtmlContent = "<h1>Report for User 1</h1>" },
            new User { Id = "user2", HtmlContent = "<h1>Report for User 2</h1>" },
            new User { Id = "user3", HtmlContent = "<h1>Report for User 3</h1>" }
        };
        // Generate PDFs concurrently
        var renderer = new ChromePdfRenderer();
        Parallel.ForEach(users, user =>
        {
            var pdf = pdfReports.GetOrAdd(user.Id, id =>
            {
                var pdfDoc = renderer.RenderHtmlAsPdf(user.HtmlContent);
                return pdfDoc.BinaryData;
            });
            SaveToFile(pdf, $"{user.Id}.pdf");
        });
        Console.WriteLine("PDF generation complete.");
    }
    // Utility method to write PDF binary data to file
    static void SaveToFile(byte[] pdfBytes, string filePath)
    {
        File.WriteAllBytes(filePath, pdfBytes);
        Console.WriteLine($"Saved: {filePath}");
    }
}
// Simple user class with ID and HTML content
public class User
{
    public string Id { get; set; }
    public string HtmlContent { get; set; }
}
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
using IronPdf;
public class Program
{
    static ConcurrentDictionary<string, byte[]> pdfReports =
        new ConcurrentDictionary<string, byte[]>();
    static void Main(string[] args)
    {
        // Simulated user list with HTML content
        var users = new List<User>
        {
            new User { Id = "user1", HtmlContent = "<h1>Report for User 1</h1>" },
            new User { Id = "user2", HtmlContent = "<h1>Report for User 2</h1>" },
            new User { Id = "user3", HtmlContent = "<h1>Report for User 3</h1>" }
        };
        // Generate PDFs concurrently
        var renderer = new ChromePdfRenderer();
        Parallel.ForEach(users, user =>
        {
            var pdf = pdfReports.GetOrAdd(user.Id, id =>
            {
                var pdfDoc = renderer.RenderHtmlAsPdf(user.HtmlContent);
                return pdfDoc.BinaryData;
            });
            SaveToFile(pdf, $"{user.Id}.pdf");
        });
        Console.WriteLine("PDF generation complete.");
    }
    // Utility method to write PDF binary data to file
    static void SaveToFile(byte[] pdfBytes, string filePath)
    {
        File.WriteAllBytes(filePath, pdfBytes);
        Console.WriteLine($"Saved: {filePath}");
    }
}
// Simple user class with ID and HTML content
public class User
{
    public string Id { get; set; }
    public string HtmlContent { get; set; }
}
Imports System
Imports System.Collections.Concurrent
Imports System.Collections.Generic
Imports System.IO
Imports System.Threading.Tasks
Imports IronPdf
Public Class Program
	Private Shared pdfReports As New ConcurrentDictionary(Of String, Byte())()
	Shared Sub Main(ByVal args() As String)
		' Simulated user list with HTML content
		Dim users = New List(Of User) From {
			New User With {
				.Id = "user1",
				.HtmlContent = "<h1>Report for User 1</h1>"
			},
			New User With {
				.Id = "user2",
				.HtmlContent = "<h1>Report for User 2</h1>"
			},
			New User With {
				.Id = "user3",
				.HtmlContent = "<h1>Report for User 3</h1>"
			}
		}
		' Generate PDFs concurrently
		Dim renderer = New ChromePdfRenderer()
		Parallel.ForEach(users, Sub(user)
			Dim pdf = pdfReports.GetOrAdd(user.Id, Function(id)
				Dim pdfDoc = renderer.RenderHtmlAsPdf(user.HtmlContent)
				Return pdfDoc.BinaryData
			End Function)
			SaveToFile(pdf, $"{user.Id}.pdf")
		End Sub)
		Console.WriteLine("PDF generation complete.")
	End Sub
	' Utility method to write PDF binary data to file
	Private Shared Sub SaveToFile(ByVal pdfBytes() As Byte, ByVal filePath As String)
		File.WriteAllBytes(filePath, pdfBytes)
		Console.WriteLine($"Saved: {filePath}")
	End Sub
End Class
' Simple user class with ID and HTML content
Public Class User
	Public Property Id() As String
	Public Property HtmlContent() As String
End Class
$vbLabelText   $csharpLabel

Gespeicherte Dateien

C# Concurrentdictionary (Wie es für Entwickler funktioniert): Abbildung 2 - Beispiel gespeicherte Dateien

Beispiel Output

C# Concurrentdictionary (Wie es für Entwickler funktioniert): Abbildung 3 - Beispiel PDF-Dokument

Code-Zerlegung

Dieses Beispiel zeigt, wie man ConcurrentDictionary<TKey, TValue> mit IronPDF kombiniert, um PDFs in einer threadsicheren Weise zu generieren. Es ist perfekt für Apps, in denen mehrere Threads gleichzeitig PDF-Dateien verarbeiten und zwischenspeichern.

Warum ConcurrentDictionary?

  • Gewährleistet threadsicheren Zugriff auf Schlüssel-Wert-Paare.
  • GetOrAdd() vermeidet doppelte PDF-Erzeugung.
  • Keine manuellen Locks erforderlich – perfekt für hohe Parallelität. Wie es funktioniert

  • Eine Liste von Benutzern, von denen jeder eine ID und HTML hat.
  • Parallel.ForEach startet Threads zur Generierung von PDFs.
  • Jeder Thread verwendet GetOrAdd(), um entweder das PDF abzurufen oder zu erstellen.
  • Das PDF wird unter Verwendung der Benutzer-ID als Dateiname gespeichert. Summary

Dieses Muster ist ideal, wenn:

  • Sie PDFs für viele Benutzer gleichzeitig erzeugen.
  • Sie sowohl Leistung als auch Threadsicherheit benötigen.
  • Sie saubere, zuverlässige Gleichzeitigkeit in C# möchten.

Erweiterungsmethoden und Zugriffsmuster

Während ConcurrentDictionary nicht alle LINQ-Funktionen bereitstellt, können Sie dennoch Erweiterungsmethoden nutzen, um Werte abzufragen:

var completedKeys = pdfReports.Keys.Where(k => k.StartsWith("done-")).ToList();
var completedKeys = pdfReports.Keys.Where(k => k.StartsWith("done-")).ToList();
Dim completedKeys = pdfReports.Keys.Where(Function(k) k.StartsWith("done-")).ToList()
$vbLabelText   $csharpLabel

Vermeiden Sie jedoch, sich auf Elemente zu verlassen, die während der Iteration kopiert werden, da sich das Wörterbuch ändern kann. Verwenden Sie .ToList() oder .ToArray(), um bei Bedarf mit einem Snapshot zu arbeiten.

Abschluss: Thread-Sicherheit trifft auf PDF-Automatisierung

Das ConcurrentDictionary<TKey, TValue> ist ideal für Szenarien, in denen mehrere Threads Schlüssel-Wert-Paare gleichzeitig lesen/schreiben müssen—es ist der perfekte Begleiter für IronPDF in multithreaded Anwendungen.

Ob Sie gerenderte PDFs zwischenspeichern, den Auftragsstatus verfolgen oder redundante Operationen verhindern, die Verwendung dieser threadsicheren Sammlung stellt sicher, dass Ihre Logik mit Leistung und Zuverlässigkeit skaliert.

Testen Sie IronPDF noch heute

Bereit, hochleistungsfähige PDF-Anwendungen mit vollständiger Threadsicherheit zu entwickeln? Laden Sie eine kostenlose Testversion von IronPDF herunter und erleben Sie nahtlose PDF-Generierung kombiniert mit der Leistung von C#'s ConcurrentDictionary.

Häufig gestellte Fragen

Wie verbessert ein ConcurrentDictionary die Leistung in Multi-Threaded-C#-Anwendungen?

Ein ConcurrentDictionary verbessert die Leistung in Multi-Threaded-C#-Anwendungen, indem es mehreren Threads erlaubt, Operationen wie Einfügungen, Aktualisierungen und Abfragen gleichzeitig ohne externe Sperren durchzuführen, wodurch die Datenintegrität gewahrt bleibt.

Welche Bedeutung hat die Verwendung von ConcurrentDictionary mit IronPDF?

Die Verwendung von ConcurrentDictionary mit IronPDF ist von Bedeutung, da sie eine threadsichere Verwaltung von Daten während der parallelen PDF-Verarbeitung ermöglicht und sicherstellt, dass die PDF-Generierung effizient und frei von Datenkonflikten in Multi-Threaded-Umgebungen ist.

Kann ConcurrentDictionary zur Verwaltung der parallelen PDF-Generierung in C# verwendet werden?

Ja, ConcurrentDictionary kann zur Verwaltung der parallelen PDF-Generierung in C# verwendet werden, indem sichergestellt wird, dass Operationen sicher über mehrere Threads hinweg ausgeführt werden, was die Effizienz und Zuverlässigkeit des PDF-Generierungsprozesses verbessert.

Warum ist Thread-Sicherheit bei der PDF-Generierung in C# wichtig?

Thread-Sicherheit ist bei der PDF-Generierung in C# wichtig, um Datenkorruption zu vermeiden und konsistente Ausgaben zu gewährleisten, insbesondere wenn mehrere Threads an der dynamischen Erstellung und Änderung von PDF-Dokumenten beteiligt sind.

Welche Operationen können mit ConcurrentDictionary gleichzeitig ausgeführt werden?

Operationen wie Einfügungen, Aktualisierungen, Abfragen und Entfernungen können gleichzeitig mit ConcurrentDictionary ausgeführt werden, was es ideal für Hochleistungsanwendungen macht, die eine threadsichere Datenverwaltung erfordern.

Wie handhabt IronPDF konkurrierende Operationen?

IronPDF handhabt konkurrierende Operationen durch die Verwendung von threadsicheren Sammlungen wie ConcurrentDictionary, was eine effiziente PDF-Verarbeitung und Datenverwaltung über mehrere Threads hinweg ermöglicht, ohne die Datenintegrität zu gefährden.

Ist es notwendig, externe Sperren bei der Verwendung von ConcurrentDictionary zu implementieren?

Nein, es ist nicht notwendig, externe Sperren bei der Verwendung von ConcurrentDictionary zu implementieren, da es so konzipiert ist, dass es von Natur aus threadsicher ist und konkurrierende Operationen intern verwaltet.

Wie können Entwickler die PDF-Verarbeitung in C#-Anwendungen optimieren?

Entwickler können die PDF-Verarbeitung in C#-Anwendungen optimieren, indem sie threadsichere Sammlungen wie ConcurrentDictionary mit Bibliotheken wie IronPDF integrieren, was eine effiziente und zuverlässige parallele Verarbeitung von PDF-Dokumenten ermöglicht.

Jacob Mellor, Chief Technology Officer @ Team Iron
Chief Technology Officer

Jacob Mellor ist Chief Technology Officer bei Iron Software und ein visionärer Ingenieur, der führend in der C# PDF-Technologie ist. Als ursprünglicher Entwickler der Iron Software-Kerncodebasis hat er die Produktarchitektur des Unternehmens seit seiner Gründung gestaltet und zusammen mit CEO Cameron Rimington in ein Unternehmen ...

Weiterlesen