Passer au contenu du pied de page
.NET AIDE

C# Concurrentdictionary (Comment ça fonctionne pour les développeurs)

Lorsqu'on travaille avec des applications multi-thread en C#, maintenir l'intégrité des données est crucial, surtout lorsque vous générez des documents PDF à la volée en utilisant une bibliothèque comme IronPDF. The ConcurrentDictionary<tkey, tvalue> class provides a thread-safe collection to manage key and value pairs efficiently, even when multiple threads concurrently perform operations like insertions, updates, or lookups.

Dans ce guide, nous explorerons comment fonctionne ConcurrentDictionary, comment il peut s'intégrer à IronPDF pour le traitement parallèle des PDF, et ce que chaque développeur .NET doit savoir sur le type de clé, la sécurité des threads, et les pièges courants comme la gestion d'une clé existante ou l'assurance de la cohérence des données.

Qu'est-ce qu'un ConcurrentDictionary en C°?

La classe ConcurrentDictionary<tkey, tvalue>, faisant partie de l'espace de noms System.Collections.Concurrent, est une collection générique conçue pour des opérations performantes et sûres. Contrairement à un dictionnaire ordinaire, elle permet à plusieurs threads d'accéder et de modifier la collection sans verrouiller toute la structure.

Une nouvelle instance de ConcurrentDictionary<string, string> pourrait ressembler à ceci :

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

Vous pouvez définir vos propres types TKey et TValue en fonction de votre cas d'utilisation spécifique, comme la mise en cache des chemins de fichiers PDF rendus ou le suivi des tâches de génération de PDF concurrentes.

Pourquoi utiliser ConcurrentDictionary avec IronPDF?

Imaginez que vous construisez un programme qui génère des factures personnalisées en utilisant IronPDF pour des milliers d'utilisateurs. Si chaque thread doit rendre un document et stocker son résultat, un dictionnaire classique introduirait des conditions de concurrence ou déclencherait des exceptions si une clé existe déjà.

L'utilisation de ConcurrentDictionary assure :

  • Cohérence des données entre les threads
  • Lectures et écritures efficaces
  • Prévention d'erreurs de code inconnues
  • Aucun surcoût de verrouillage lorsque plusieurs threads opèrent sur des clés différentes

Méthodes communes et leur utilisation avec IronPDF

Décomposons les méthodes clés en utilisant des scénarios de rendu IronPDF.

Méthode GetOrAdd : Récupérer ou Ajouter une nouvelle clé

Cette méthode vérifie si une clé spécifiée existe. Si ce n'est pas le cas, elle ajoute la nouvelle valeur.

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
  • Assure la sécurité des threads
  • Évite le rendu en double
  • Retourne la valeur associée pour la clé donnée

Méthode AddOrUpdate : Gérer une valeur existante avec grâce

Cette méthode vous permet de mettre à jour la valeur si la clé existe, ou d'ajouter une nouvelle paire clé-valeur.

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
  • Gère la logique pour une clé existante
  • S'assure que les membres accédés sont sûrs en simultané

Méthode TryAdd : Ajouter si la clé n'existe pas

Cette méthode essaie d'ajouter une valeur et renvoie une valeur booléenne indiquant le succès.

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
  • Parfaite pour éviter les conflits
  • La méthode retourne true si l'insertion réussit

Tableau des cas d'utilisation : Méthodes ConcurrentDictionary

ConcurrentDictionary en C# (Comment ça fonctionne pour les développeurs) : Figure 1 - Tableau des cas d'utilisation

Optimiser pour la performance

ConcurrentDictionary prend en charge le réglage via le constructeur :

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
  • niveau de concurrence : Nombre de threads attendus (valeur par défaut = niveau de concurrence par défaut)
  • capacité initiale : Nombre d'éléments attendus (capacité initiale par défaut)

Un réglage approprié améliore le débit et réduit le contentieux entre les threads multiples.

Prévenir les problèmes avec les conflits de clés et les valeurs par défaut

Lorsqu'une clé n'existe pas, des opérations comme TryGetValue peuvent renvoyer la valeur par défaut pour le type :

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

Cela protège votre code contre des codes inconnus ou des références nulles. Vérifiez toujours une valeur spécifique avant de supposer sa présence.

Exemple pratique : Générateur de rapports IronPDF sûr pour les threads

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

Fichiers enregistrés

ConcurrentDictionary en C# (Comment ça fonctionne pour les développeurs) : Figure 2 - Exemples de fichiers enregistrés comme indiqué

Exemple de sortie

ConcurrentDictionary en C# (Comment ça fonctionne pour les développeurs) : Figure 3 - Exemple de document PDF

Décomposition du code

Cet exemple démontre comment combiner ConcurrentDictionary<TKey, TValue> avec IronPDF pour générer des PDFs en toute sécurité. C'est parfait pour les applications où plusieurs threads traitent et mettent en cache des fichiers PDF simultanément.

Pourquoi ConcurrentDictionary?

  • Assure un accès sûr aux paires clé-valeur.
  • GetOrAdd() évite la génération de PDF en double.
  • Pas de verrouillage manuel nécessaire — parfait pour une forte concurrence. Comment ça fonctionne

  • Une liste d'utilisateurs dispose chacun d'un ID et HTML.
  • Parallel.ForEach spawn des threads pour générer des PDFs.
  • Chaque thread utilise GetOrAdd() pour soit récupérer, soit créer le PDF.
  • Le PDF est sauvegardé en utilisant l'ID de l'utilisateur comme nom de fichier. Résumé

Ce modèle est idéal lorsque :

  • Vous générez des PDFs pour de nombreux utilisateurs en même temps.
  • Vous avez besoin de performance et de sécurité en matière de threads.
  • Vous voulez une concurrence propre, fiable en C#.

Méthodes d'extension et modèles d'accès

Bien que ConcurrentDictionary n'expose pas toutes les fonctionnalités de LINQ, vous pouvez toujours utiliser des méthodes d'extension pour interroger les valeurs :

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

Cependant, évitez de vous fier aux éléments copiés pendant l'itération car le dictionnaire peut changer. Utilisez .ToList() ou .ToArray() pour travailler avec un instantané si nécessaire.

Conclusion : Sécurité des threads et automatisation PDF

Le ConcurrentDictionary<TKey, TValue> est idéal pour les scénarios où plusieurs threads doivent lire/écrire des paires clé-valeur simultanément, ce qui en fait le compagnon parfait pour IronPDF dans des applications multi-thread.

Que vous mettiez en cache des PDFs rendus, suiviez l'état des travaux ou évitiez les opérations redondantes, utiliser cette collection sûre pour les threads assure que votre logique évolue avec performance et fiabilité.

Essayez IronPDF Aujourd'hui

Prêt à construire des applications PDF performantes avec une sécurité complète des threads ? Téléchargez une version d'essai gratuite d'IronPDF et découvrez la génération de PDF sans faille combinée à la puissance de ConcurrentDictionary de C#.

Questions Fréquemment Posées

Comment un ConcurrentDictionary améliore-t-il les performances dans les applications C# multithreadées ?

Un ConcurrentDictionary améliore les performances dans les applications C# multithreadées en permettant à plusieurs threads d'effectuer des opérations telles que des insertions, des mises à jour et des recherches de manière concurrente sans avoir besoin de verrous externes, maintenant ainsi l'intégrité des données.

Quelle est l'importance d'utiliser ConcurrentDictionary avec IronPDF ?

Utiliser ConcurrentDictionary avec IronPDF est important car cela permet une gestion sécurisée des données lors du traitement parallèle des PDF, garantissant que la génération de PDF est efficace et sans conflits de données dans des environnements multithreadés.

ConcurrentDictionary peut-il être utilisé pour gérer la génération concurrente de PDF en C# ?

Oui, ConcurrentDictionary peut être utilisé pour gérer la génération concurrente de PDF en C# en s'assurant que les opérations sont gérées en toute sécurité à travers plusieurs threads, améliorant ainsi l'efficacité et la fiabilité du processus de génération de PDF.

Pourquoi la sécurité des threads est-elle importante lors de la génération de PDF en C# ?

La sécurité des threads est importante lors de la génération de PDF en C# pour éviter la corruption des données et assurer une sortie cohérente, en particulier lorsque plusieurs threads sont impliqués dans la création et la modification dynamiques des documents PDF.

Quelles opérations peuvent être effectuées de manière concurrente en utilisant ConcurrentDictionary ?

Les opérations telles que les insertions, les mises à jour, les recherches et les suppressions peuvent être effectuées de manière concurrente en utilisant ConcurrentDictionary, ce qui le rend idéal pour les applications haute performance nécessitant une gestion sécurisée des données.

Comment IronPDF gère-t-il les opérations concurrentes ?

IronPDF gère les opérations concurrentes en utilisant des collections sûres pour les threads comme ConcurrentDictionary, ce qui permet un traitement efficace des PDF et une gestion des données à travers plusieurs threads sans risquer l'intégrité des données.

Est-il nécessaire de mettre en œuvre un verrouillage externe lors de l'utilisation de ConcurrentDictionary ?

Non, il n'est pas nécessaire de mettre en œuvre un verrouillage externe lors de l'utilisation de ConcurrentDictionary, car il est conçu pour être intrinsèquement sûr pour les threads, gérant les opérations concurrentes en interne.

Comment les développeurs peuvent-ils optimiser le traitement des PDF dans les applications C# ?

Les développeurs peuvent optimiser le traitement des PDF dans les applications C# en intégrant des collections sûres pour les threads comme ConcurrentDictionary avec des bibliothèques telles qu'IronPDF, permettant un traitement parallèle efficace et fiable des documents PDF.

Curtis Chau
Rédacteur technique

Curtis Chau détient un baccalauréat en informatique (Université de Carleton) et se spécialise dans le développement front-end avec expertise en Node.js, TypeScript, JavaScript et React. Passionné par la création d'interfaces utilisateur intuitives et esthétiquement plaisantes, Curtis aime travailler avec des frameworks modernes ...

Lire la suite