跳過到頁腳內容
.NET幫助

C# Concurrentdictionary(它是如何運作的開發者用途)

在 C# 中使用多執行緒應用程式時,維護資料的完整性至關重要,尤其是當您使用 IronPDF 之類的函式庫來快速產生 PDF 文件時。 ConcurrentDictionary<tkey, tvalue> 類提供了一個線程安全的集合,即使在多個線程同時執行插入、更新或查詢等作業時,也能有效地管理鍵和值對。

在本指南中,我們將探討 ConcurrentDictionary 如何運作、如何與 IronPDF 整合以進行 並行 PDF 處理,以及每位 .NET 開發人員都需要瞭解的關鍵類型、線程安全,以及處理既有關鍵或確保資料一致性等常見陷阱。

C# 中的 ConcurrentDictionary 是什麼?

ConcurrentDictionary<tkey, tvalue> 類是 System.Collections.Concurrent 命名空間的一部分,是專為高效能、線程安全操作而設計的一般集合。 與一般字典不同,它允許多個線程安全地存取和修改集合,而不會鎖定整個結構。

ConcurrentDictionary<string, string> 的新實例可能會是這樣:

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

您可以根據特定的使用情況,自行定義 TKey 和 TValue 類型,例如快取已渲染的 PDF 檔案路徑或追蹤並發的 PDF 生成工作。

為何使用 IronPDF 的 ConcurrentDictionary?

假設您正在建立一個程式,使用 IronPDF 為數以千計的使用者產生個人化的發票。 如果每個線程都需要呈現一個文件並儲存其結果,一般的字典就會引發競賽條件或在鍵已經存在時產生異常。

使用 ConcurrentDictionary 可確保:

  • 跨線程資料一致性
  • 高效讀寫
  • 預防未知程式碼錯誤
  • 當多個線程在不同的鍵上操作時,零鎖定開銷

常用方法及其在 IronPDF 中的使用。

讓我們來分解使用 IronPDF 渲染情境的主要方法。

GetOrAdd 方法:擷取或新增金鑰。

此方法會檢查指定的關鍵字是否存在。 否則就會增加新的價值。

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
  • 確保線程安全
  • 避免重複渲染
  • 返回給定鍵的關聯值

AddOrUpdate 方法:優雅地處理現有值。

此方法可讓您在鍵存在的情況下更新值,或新增鍵值對。

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
  • 管理現有關鍵邏輯
  • 確保在並發狀態下存取的成員是安全的

TryAdd 方法:如果關鍵不存在則新增。

此方法嘗試新增一個值,並返回一個表示成功的布林值。

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
  • 完美避免衝突
  • 如果插入成功,方法返回 true

使用案例表:ConcurrentDictionary 方法

C# Concurrentdictionary (How it Works for Developers):圖 1 - 使用案例表

效能最佳化

ConcurrentDictionary 支援透過建構器來調整:

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:預期的線程數 (default = 預設的並發等級)
  • initialCapacity:預期元素數量 (預設初始容量)

正確設定這些可以提高吞吐量並減少多個線程間的爭用。

預防按鍵衝突和預設值的問題

當鍵不存在時,像 TryGetValue 之類的操作可以回傳該類型的預設值:

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

這可保障您的程式碼不受不明程式碼或 null 參照的影響。 在假定存在之前,請務必檢查特定的值。

實用範例:線程安全的 IronPDF 報告產生器。

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

儲存的檔案

C# Concurrentdictionary (How it Works for Developers):圖 2 - 依指定方式儲存的範例檔案

輸出範例

C# Concurrentdictionary (How it Works for Developers):圖 3 - PDF 文件範例

程式碼分解

本範例示範如何結合 ConcurrentDictionary<TKey, TValue> 與 IronPDF,以線程安全的方式產生 PDF。 非常適合多線程同時處理和快取 PDF 檔案的應用程式。

為何選擇 ConcurrentDictionary?

  • 確保以線程安全的方式存取鍵值對。
  • GetOrAdd() 可避免重複產生 PDF。
  • 不需要手動鎖定-完美的高併發性。 如何運作

  • 使用者清單每個人都有 ID 和 HTML。
  • Parallel.ForEach 產生線程來產生 PDF。
  • 每個線程使用 GetOrAdd() 抓取或建立 PDF。
  • PDF 會以使用者的 ID 作為檔案名稱儲存。 概括

此模式適用於下列情況:

  • 您要同時為許多使用者產生 PDF。
  • 您需要效能線程安全。
  • 您想要 C# 中乾淨、可靠的並發功能。

擴充方法與存取模式

雖然 ConcurrentDictionary 並未揭露所有 LINQ 功能,但您仍可使用擴充方法來查詢數值:

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

然而,由於字典可能會變更,請避免依賴在迭代過程中複製的元素。 如有需要,請使用 .ToList() 或 .ToArray() 來處理快照。

結論:線程安全與 PDF 自動化的結合。

ConcurrentDictionary<TKey, TValue> 非常適用於多執行緒需要同時讀取/寫入鍵值對的情況,使其成為多執行緒應用程式中 IronPDF 的完美搭配。

無論是快取已渲染的 PDF、追蹤作業狀態,或是防止多餘的作業,使用此線程安全集合可確保您的邏輯擴充效能與可靠性。

立即試用 IronPDF

準備好以完整的線程安全性建立高效能的 PDF 應用程式了嗎? 下載 IronPDF 免費試用版,體驗結合 C# 的 ConcurrentDictionary 強大功能的無縫 PDF 生成。

常見問題解答

ConcurrentDictionary 如何在多執行緒 C# 應用程序中增強性能?

ConcurrentDictionary 通過允許多個執行緒同時执行插入、更新和查找等操作,而無需外部鎖,從而在多執行緒 C# 應用程序中增強性能,並维护數據完整性。

使用 ConcurrentDictionary 与 IronPDF 的意义是什么?

使用 ConcurrentDictionary 与 IronPDF 具有重要意义,因為它可以在執行緒安全管理並行 PDF 處理數據,確保在多執行緒环境下 PDF 生成高效且無數據冲突。

可以使用 ConcurrentDictionary 管理 C# 中的並發 PDF 生成嗎?

是的,可以使用 ConcurrentDictionary 來管理 C# 中的並發 PDF 生成,確保操作跨多個執行緒安全處理,提高 PDF 生成過程的效率和可靠性。

在 C# 中生成 PDF 時,為什么執行緒安全很重要?

在 C# 中生成 PDF 時,執行緒安全很重要,以防止數據损坏並確保輸出一致性,特别是在多個執行緒參與動態创建和修改 PDF 文檔時。

使用 ConcurrentDictionary 可以同時执行哪些操作?

可以同時执行插入、更新、查找和删除等操作,ConcurrentDictionary 使得它非常適合需要執行緒安全數據管理的高性能應用程序。

IronPDF 如何處理並發操作?

IronPDF 通過利用像 ConcurrentDictionary 這样的執行緒安全集合來處理並發操作,使得 PDF 處理高效,並在多個執行緒中管理數據而不危及數據完整性。

在使用 ConcurrentDictionary 時有必要實現外部鎖定嗎?

不,使用 ConcurrentDictionary 時不需要實現外部鎖定,因為它設计為天生執行緒安全,管理內部的並發操作。

開發人员如何優化 C# 應用程序中的 PDF 處理?

開發人员可以通過将執行緒安全集合如 ConcurrentDictionary 与 IronPDF 等庫集成來優化 C# 應用程序中的 PDF 處理,實現 PDF 文檔的高效可靠並行處理。

Jacob Mellor, Team Iron 首席技術官
首席技術官

Jacob Mellor是Iron Software的首席技術官,也是開創C# PDF技術的前瞻性工程師。作為Iron Software核心代碼庫的原始開發者,他自公司成立以來就塑造了公司的產品架構,並與CEO Cameron Rimington將公司轉型為服務NASA、Tesla以及全球政府機構的50多人公司。

Jacob擁有曼徹斯特大學土木工程一級榮譽學士學位(1998年–2001年)。他於1999年在倫敦開立首家軟體公司,並於2005年建立了他的第一個.NET組件,專注於解決Microsoft生態系統中的複雜問題。

他的旗艦作品IronPDF和Iron Suite .NET程式庫全球已獲得超過3000萬次NuGet安裝,他的基礎代碼不斷在全球各地驅動開發者工具。擁有25年以上的商業經驗和41年的編碼專業知識,Jacob仍然專注於推動企業級C#、Java和Python PDF技術的創新,同時指導下一代技術領導者。

鋼鐵支援團隊

我們每週 5 天,每天 24 小時在線上。
聊天
電子郵件
打電話給我