
Dicionário Concorrente em C# (Como funciona para desenvolvedores)
Ao trabalhar com aplicações multithread em C#, manter a integridade dos dados é crucial, especialmente ao gerar documentos PDF dinamicamente usando uma biblioteca como o IronPDF . O Dicionário Concorrente<tkey, tvalue> A classe fornece uma coleção thread-safe para gerenciar pares de chave e valor de forma eficiente, mesmo quando várias threads executam operações como inserções, atualizações ou pesquisas simultaneamente.
Neste guia, exploraremos como o ConcurrentDictionary funciona, como ele pode ser integrado ao IronPDF para processamento paralelo de PDFs e o que todo desenvolvedor .NET precisa saber sobre tipo de chave, segurança de threads e problemas comuns, como lidar com uma chave existente ou garantir a consistência dos dados.
What is a ConcurrentDictionary in C#?
O Dicionário Concorrente<tkey, tvalue> A classe Collection, parte do namespace System.Collections.Concurrent, é uma coleção genérica projetada para operações de alto desempenho e seguras para threads. Diferentemente de um dicionário comum, ele permite que múltiplas threads acessem e modifiquem a coleção com segurança, sem bloquear toda a estrutura.
Uma nova instância de ConcurrentDictionary<string, string> pode ter esta aparência:
var dictionary = new ConcurrentDictionary<string, string>();Dim dictionary = New ConcurrentDictionary(Of String, String)()Você pode definir seus próprios tipos TKey e TValue com base em seu caso de uso específico, como armazenar em cache os caminhos de arquivos PDF renderizados ou rastrear tarefas simultâneas de geração de PDF.
Por que usar o ConcurrentDictionary com o IronPDF?
Imagine que você está criando um programa que gera faturas personalizadas usando o IronPDF para milhares de usuários. Se cada thread precisar renderizar um documento e armazenar seu resultado, um dicionário comum introduziria condições de corrida ou lançaria exceções se uma chave já existisse.
O uso de ConcurrentDictionary garante:
- Consistência de dados entre threads
- Leitura e escrita eficientes
- Prevenção de erros de código desconhecidos
- Sobrecarga de bloqueio zero quando várias threads operam em teclas diferentes.
Métodos comuns e sua utilização com o IronPDF
Vamos analisar os principais métodos usando cenários de renderização do IronPDF .
Método GetOrAdd: Recuperar ou adicionar uma nova chave
Este método verifica se uma chave especificada existe. Caso contrário, adiciona o novo valor.
var filePath = pdfCache.GetOrAdd(userId, id => GeneratePdfForUser(id));Dim filePath = pdfCache.GetOrAdd(userId, Function(id) GeneratePdfForUser(id))- Garante a segurança de threads
- Evita renderização duplicada
- Retorna o valor associado à chave fornecida.
Método AddOrUpdate: Lidar com um valor existente de forma adequada
Este método permite que você atualize o valor se a chave existir, ou adicione um novo par chave-valor.
pdfCache.AddOrUpdate(userId,
id => GeneratePdfForUser(id),
(id, existingValue) => UpdatePdfForUser(id, existingValue));pdfCache.AddOrUpdate(userId, Function(id) GeneratePdfForUser(id), Function(id, existingValue) UpdatePdfForUser(id, existingValue))- Gerencia a lógica para chaves existentes
- Garante a segurança dos membros acessados em situações de acesso simultâneo.
Método TryAdd: Adicionar se a chave não existir
Este método tenta adicionar um valor e retorna um valor booleano indicando sucesso.
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- Ideal para evitar conflitos
- O método retorna verdadeiro se a inserção for bem-sucedida.
Tabela de casos de uso: Métodos do ConcurrentDictionary

Otimizando para o desempenho
O ConcurrentDictionary suporta ajustes através do construtor:
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)- concurrencyLevel: Número esperado de threads (padrão = nível de concorrência padrão)
- initialCapacity: Número esperado de elementos (capacidade inicial padrão)
Configurar esses parâmetros corretamente melhora o desempenho e reduz a disputa entre várias threads.
Prevenindo problemas com conflitos de teclas e valores padrão
Quando uma chave não existe, operações como TryGetValue podem retornar o valor padrão para o tipo:
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 IfIsso protege seu código contra código desconhecido ou referências nulas. Sempre verifique um valor específico antes de presumir a presença de algo.
Exemplo prático: Gerador de relatórios IronPDF seguro para 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; }
}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 ClassArquivos salvos

Exemplo de saída

Análise do código
Este exemplo demonstra como combinar ConcurrentDictionary<TKey, TValue> Utilize o IronPDF para gerar PDFs de forma segura para múltiplos threads. É perfeito para aplicativos onde várias threads processam e armazenam arquivos PDF em cache simultaneamente.
Por que usar um ConcurrentDictionary?
-
Garante acesso seguro a pares de chave-valor em ambientes com múltiplas threads.
-
A função GetOrAdd() evita a geração de PDFs duplicados.
-
Não são necessárias fechaduras manuais — perfeito para alta concorrência. Como funciona
-
Uma lista de usuários, cada um com um ID e um HTML.
-
O Parallel.ForEach cria threads para gerar PDFs.
-
Cada thread usa
GetOrAdd()para buscar ou criar o PDF. -
O PDF é salvo usando o ID do usuário como nome do arquivo. Resumo
Este padrão é ideal quando:
Você está gerando PDFs para vários usuários ao mesmo tempo.
- Você precisa de desempenho e segurança da rosca. Você deseja concorrência limpa e confiável em C#.
Métodos de extensão e padrões de acesso
Embora o ConcurrentDictionary não exponha todos os recursos do LINQ, você ainda pode usar métodos de extensão para consultar valores:
var completedKeys = pdfReports.Keys.Where(k => k.StartsWith("done-")).ToList();Dim completedKeys = pdfReports.Keys.Where(Function(k) k.StartsWith("done-")).ToList()No entanto, evite depender de elementos copiados durante a iteração, pois o dicionário pode mudar. Use .ToList() ou .ToArray() para trabalhar com um instantâneo, se necessário.
Conclusão: Segurança de roscas aliada à automação de PDF
O ConcurrentDictionary<TKey, TValue> é ideal para cenários onde múltiplas threads precisam ler/escrever pares chave-valor simultaneamente—tornando-o um perfeito companheiro para IronPDF em aplicações multithread.
Seja armazenando em cache PDFs renderizados, rastreando o status de trabalhos ou prevenindo operações redundantes, usar esta coleção thread-safe garante que sua lógica escale com desempenho e confiabilidade.
Experimente o IronPDF hoje mesmo!
Pronto para criar aplicativos PDF de alto desempenho com total segurança de threads? Baixe uma versão de avaliação gratuita do IronPDF e experimente a geração perfeita de PDFs combinada com o poder do ConcurrentDictionary do C#.

Curtis Chau é bacharel em Ciência da Computação (Universidade Carleton) e se especializa em desenvolvimento front-end, com experiência em Node.js, TypeScript, JavaScript e React. Apaixonado por criar interfaces de usuário intuitivas e esteticamente agradáveis, Curtis gosta de trabalhar com frameworks modernos e criar manuais bem estruturados e visualmente atraentes.
Artigos relacionados


