.NET幫助 C# 並發列表(開發者的工作原理) Jacob Mellor 更新:7月 28, 2025 下載 IronPDF NuGet 下載 DLL 下載 Windows 安裝程式 開始免費試用 法學碩士副本 法學碩士副本 將頁面複製為 Markdown 格式,用於 LLMs 在 ChatGPT 中打開 請向 ChatGPT 諮詢此頁面 在雙子座打開 請向 Gemini 詢問此頁面 在雙子座打開 請向 Gemini 詢問此頁面 打開困惑 向 Perplexity 詢問有關此頁面的信息 分享 在 Facebook 上分享 分享到 X(Twitter) 在 LinkedIn 上分享 複製連結 電子郵件文章 如果您曾經讓多個線程爭奪共用資源的存取權,您就會知道線程安全的實作並不是遊戲。 不過不用擔心! C# 已為您提供並發集合 - 一套功能強大的線程安全、泛型集合類別,可確保線程安全,且風格優雅。 C# 中的線程安全與並發集合; 讓我們先想像一個沒有紅綠燈的熱鬧城市十字路口。 您可以想像當時的混亂情況! 這類似於當多個線程同時訪問共享資源而沒有適當的系統時發生的情況。 值得慶幸的是,在 C# 中,我們的線程有交通燈 - 這些稱為並發集合。 它們是集合類別,一次只允許一個線程存取資源。當使用多個線程工作時,這種線程安全性是至關重要的。 探索 C# 中的並發線程安全集合; 在 C# 中,命名空間 System.Collections.Concurrent 包含多種並發集合類別,例如 ConcurrentDictionary, ConcurrentQueue, ConcurrentStack 以及 ConcurrentBag 。 這些無序集合類別提供了其非並行對應類型的線程安全版本。 並發集合的與眾不同之處在於它們是無序的並發集合,這意味著元素沒有特定的順序。 舉例來說,對於並發清單,您無法確切知道項目插入的位置。 重點在於確保線程安全,而非維持秩序。 讓我們舉一個真實的例子。 想想網站的密碼提交貼文。透過並發集合,多位使用者可以同時提交密碼。 每個"提交"動作就像一個線程,並發集合可確保每個提交都是線程安全、處理安全且有效率的。 ConcurrentDictionary:真實世界的範例 現在,讓我們以實際的範例來探討 ConcurrentDictionary 集合類別。 想像一個具有推薦功能的線上書店。 使用者的每次點選都會將一本書加入個人推薦清單,並以字典為代表。 由於有多位使用者同時瀏覽和點選書籍,因此我們有多個線程同時存取字典。 C# 中的 ConcurrentDictionary 應該是這樣的: using System.Collections.Concurrent; ConcurrentDictionary<string, string> recommendedBooks = new ConcurrentDictionary<string, string>(); using System.Collections.Concurrent; ConcurrentDictionary<string, string> recommendedBooks = new ConcurrentDictionary<string, string>(); Imports System.Collections.Concurrent Private recommendedBooks As New ConcurrentDictionary(Of String, String)() $vbLabelText $csharpLabel 若要將書籍加入使用者的整個推薦集合,我們可以使用 TryAdd 方法: public void Insert(string user, string book) { // Try to add the book to the user's recommendations recommendedBooks.TryAdd(user, book); } public void Insert(string user, string book) { // Try to add the book to the user's recommendations recommendedBooks.TryAdd(user, book); } Public Sub Insert(ByVal user As String, ByVal book As String) ' Try to add the book to the user's recommendations recommendedBooks.TryAdd(user, book) End Sub $vbLabelText $csharpLabel 在此情境中,ConcurrentDictionary 集合類別可確保每次點選(或稱為"線程")都會單獨處理,因此不會混淆兩個使用者的建議。它會處理所有的線程安全,因此您不必擔心資料競賽以及其他與多線程相關聯的並發問題。 實現線程安全作業 除了 TryAdd 之外,C# 中的並發集合提供了多種其他線程安全的操作,例如 TryRemove 和 TryUpdate 。 這些方法可確保一次只能有一個線程執行操作。因此,舉例來說,如果我們想要從上一個範例中的使用者推薦中移除一本书,我們可以使用 TryRemove 方法: public void RemoveAt(string user) { // Attempt to remove the book for the specified user string removedBook; recommendedBooks.TryRemove(user, out removedBook); } public void RemoveAt(string user) { // Attempt to remove the book for the specified user string removedBook; recommendedBooks.TryRemove(user, out removedBook); } Public Sub RemoveAt(ByVal user As String) ' Attempt to remove the book for the specified user Dim removedBook As String = Nothing recommendedBooks.TryRemove(user, removedBook) End Sub $vbLabelText $csharpLabel TryRemove 方法將嘗試移除所提供的關鍵值 (在本例中為使用者),並將其放入 removedBook 變數中。 複製並發集合 現在,假設您想要將您的並發集合複製到陣列中。 Concurrent 集合提供了一個 CopyTo 方法,正是為了這個目的: public void CopyTo() { // Create an array to hold the recommended books string[] bookArray = new string[recommendedBooks.Count]; // Copy the values of the concurrent dictionary to the array recommendedBooks.Values.CopyTo(bookArray, 0); } public void CopyTo() { // Create an array to hold the recommended books string[] bookArray = new string[recommendedBooks.Count]; // Copy the values of the concurrent dictionary to the array recommendedBooks.Values.CopyTo(bookArray, 0); } Public Sub CopyTo() ' Create an array to hold the recommended books Dim bookArray(recommendedBooks.Count - 1) As String ' Copy the values of the concurrent dictionary to the array recommendedBooks.Values.CopyTo(bookArray, 0) End Sub $vbLabelText $csharpLabel 在此,CopyTo 方法會將 recommendedBooks 並發字典中的所有書籍 (值) 複製到 bookArray 中。 線程安全收集 C# 也提供 thread-safe 集合,其目的是確保在多執行緒環境中安全存取共用資源。 這些集合(例如 ConcurrentBag、ConcurrentQueue 和 ConcurrentStack)提供線程安全的實作,多個線程可以同時存取和修改集合,而不會造成衝突或資料損毀。 這些工具透過內部處理同步化來保證一致性和完整性,因此非常適用於無序集合已足夠的情況,而線程安全在您的 C# 應用程式中是最重要的。 瞭解更多關於 IronPDF 是一個廣受歡迎的 C# 函式庫,可讓您毫不費力地從 HTML 產生 PDF 文件。 using IronPdf; class Program { static void Main(string[] args) { var renderer = new ChromePdfRenderer(); // 1. Convert HTML String to PDF var htmlContent = "<h1>Hello, IronPDF!</h1><p>This is a PDF from an HTML string.</p>"; var pdfFromHtmlString = renderer.RenderHtmlAsPdf(htmlContent); pdfFromHtmlString.SaveAs("HTMLStringToPDF.pdf"); // 2. Convert HTML File to PDF var htmlFilePath = "path_to_your_html_file.html"; // Specify the path to your HTML file var pdfFromHtmlFile = renderer.RenderHtmlFileAsPdf(htmlFilePath); pdfFromHtmlFile.SaveAs("HTMLFileToPDF.pdf"); // 3. Convert URL to PDF var url = "http://ironpdf.com"; // Specify the URL var pdfFromUrl = renderer.RenderUrlAsPdf(url); pdfFromUrl.SaveAs("URLToPDF.pdf"); } } using IronPdf; class Program { static void Main(string[] args) { var renderer = new ChromePdfRenderer(); // 1. Convert HTML String to PDF var htmlContent = "<h1>Hello, IronPDF!</h1><p>This is a PDF from an HTML string.</p>"; var pdfFromHtmlString = renderer.RenderHtmlAsPdf(htmlContent); pdfFromHtmlString.SaveAs("HTMLStringToPDF.pdf"); // 2. Convert HTML File to PDF var htmlFilePath = "path_to_your_html_file.html"; // Specify the path to your HTML file var pdfFromHtmlFile = renderer.RenderHtmlFileAsPdf(htmlFilePath); pdfFromHtmlFile.SaveAs("HTMLFileToPDF.pdf"); // 3. Convert URL to PDF var url = "http://ironpdf.com"; // Specify the URL var pdfFromUrl = renderer.RenderUrlAsPdf(url); pdfFromUrl.SaveAs("URLToPDF.pdf"); } } Imports IronPdf Friend Class Program Shared Sub Main(ByVal args() As String) Dim renderer = New ChromePdfRenderer() ' 1. Convert HTML String to PDF Dim htmlContent = "<h1>Hello, IronPDF!</h1><p>This is a PDF from an HTML string.</p>" Dim pdfFromHtmlString = renderer.RenderHtmlAsPdf(htmlContent) pdfFromHtmlString.SaveAs("HTMLStringToPDF.pdf") ' 2. Convert HTML File to PDF Dim htmlFilePath = "path_to_your_html_file.html" ' Specify the path to your HTML file Dim pdfFromHtmlFile = renderer.RenderHtmlFileAsPdf(htmlFilePath) pdfFromHtmlFile.SaveAs("HTMLFileToPDF.pdf") ' 3. Convert URL to PDF Dim url = "http://ironpdf.com" ' Specify the URL Dim pdfFromUrl = renderer.RenderUrlAsPdf(url) pdfFromUrl.SaveAs("URLToPDF.pdf") End Sub End Class $vbLabelText $csharpLabel 儘管 IronPDF 一開始似乎與並發清單沒有直接關係,但它可以輔助您的並發收集作業,提供簡易的方式來建立 PDF 報告、日誌或任何其他可擷取您的並發處理結果的文件。 考慮您有一個執行密集資料處理的多執行緒應用程式的情況。 當線程在資料上發揮魔力時,您可能想要擷取結果並產生 PDF 報告,以便進一步分析或記錄。 這就是 IronPdf 發揮作用的地方。 使用 IronPDF 非常簡單,只需將函式庫新增至您的專案,並使用其便利的 API 即可。 以下是如何將 IronPDF 與您的並發收集作業整合的範例: using IronPdf; using System.Collections.Concurrent; using System.Collections.Generic; using System.Threading.Tasks; // Create a concurrent dictionary to hold your processed data ConcurrentDictionary<int, string> processedData = new ConcurrentDictionary<int, string>(); // Define your data list (replace with your actual data source) List<DataItem> dataList = GetDataList(); // Process your data concurrently and store the results in the dictionary Parallel.ForEach(dataList, (dataItem) => { // Process each data item and add the result to the dictionary string processedResult = ProcessDataItem(dataItem); processedData.TryAdd(dataItem.Id, processedResult); }); // Generate a PDF report with the processed data var renderer = new ChromePdfRenderer(); var pdfDocument = renderer.RenderHtmlAsPdf(BuildHtmlReport(processedData)); pdfDocument.SaveAs("C:\\processed_data_report.pdf"); // Method to retrieve the data list (replace with your actual data source logic) List<DataItem> GetDataList() { List<DataItem> dataList = new List<DataItem>() { new DataItem { Id = 1, Name = "Item 1" }, new DataItem { Id = 2, Name = "Item 2" }, new DataItem { Id = 3, Name = "Item 3" }, new DataItem { Id = 4, Name = "Item 4" } }; return dataList; } // Method to process each data item and return the result (replace with your actual data processing logic) string ProcessDataItem(DataItem dataItem) { // Simulating data processing with a delay Task.Delay(100).Wait(); return $"Processed: {dataItem.Name}"; } // Method to build the HTML report using the processed data (replace with your actual reporting logic) string BuildHtmlReport(ConcurrentDictionary<int, string> processedData) { string html = "<h1>Processed Data Report</h1><ul>"; foreach (var kvp in processedData) { html += $"<li>Item {kvp.Key}: {kvp.Value}</li>"; } html += "</ul>"; return html; } // Placeholder class for your data item (replace with your actual data item class) public class DataItem { public int Id { get; set; } public string Name { get; set; } // Add other properties as needed } using IronPdf; using System.Collections.Concurrent; using System.Collections.Generic; using System.Threading.Tasks; // Create a concurrent dictionary to hold your processed data ConcurrentDictionary<int, string> processedData = new ConcurrentDictionary<int, string>(); // Define your data list (replace with your actual data source) List<DataItem> dataList = GetDataList(); // Process your data concurrently and store the results in the dictionary Parallel.ForEach(dataList, (dataItem) => { // Process each data item and add the result to the dictionary string processedResult = ProcessDataItem(dataItem); processedData.TryAdd(dataItem.Id, processedResult); }); // Generate a PDF report with the processed data var renderer = new ChromePdfRenderer(); var pdfDocument = renderer.RenderHtmlAsPdf(BuildHtmlReport(processedData)); pdfDocument.SaveAs("C:\\processed_data_report.pdf"); // Method to retrieve the data list (replace with your actual data source logic) List<DataItem> GetDataList() { List<DataItem> dataList = new List<DataItem>() { new DataItem { Id = 1, Name = "Item 1" }, new DataItem { Id = 2, Name = "Item 2" }, new DataItem { Id = 3, Name = "Item 3" }, new DataItem { Id = 4, Name = "Item 4" } }; return dataList; } // Method to process each data item and return the result (replace with your actual data processing logic) string ProcessDataItem(DataItem dataItem) { // Simulating data processing with a delay Task.Delay(100).Wait(); return $"Processed: {dataItem.Name}"; } // Method to build the HTML report using the processed data (replace with your actual reporting logic) string BuildHtmlReport(ConcurrentDictionary<int, string> processedData) { string html = "<h1>Processed Data Report</h1><ul>"; foreach (var kvp in processedData) { html += $"<li>Item {kvp.Key}: {kvp.Value}</li>"; } html += "</ul>"; return html; } // Placeholder class for your data item (replace with your actual data item class) public class DataItem { public int Id { get; set; } public string Name { get; set; } // Add other properties as needed } Imports IronPdf Imports System.Collections.Concurrent Imports System.Collections.Generic Imports System.Threading.Tasks ' Create a concurrent dictionary to hold your processed data Private processedData As New ConcurrentDictionary(Of Integer, String)() ' Define your data list (replace with your actual data source) Private dataList As List(Of DataItem) = GetDataList() ' Process your data concurrently and store the results in the dictionary Parallel.ForEach(dataList, Sub(dataItem) ' Process each data item and add the result to the dictionary Dim processedResult As String = ProcessDataItem(dataItem) processedData.TryAdd(dataItem.Id, processedResult) End Sub) ' Generate a PDF report with the processed data Dim renderer = New ChromePdfRenderer() Dim pdfDocument = renderer.RenderHtmlAsPdf(BuildHtmlReport(processedData)) pdfDocument.SaveAs("C:\processed_data_report.pdf") ' Method to retrieve the data list (replace with your actual data source logic) 'INSTANT VB TODO TASK: Local functions are not converted by Instant VB: 'List(Of DataItem) GetDataList() '{ ' List<DataItem> dataList = New List<DataItem>() { New DataItem { Id = 1, Name = "Item 1" }, New DataItem { Id = 2, Name = "Item 2" }, New DataItem { Id = 3, Name = "Item 3" }, New DataItem { Id = 4, Name = "Item 4" } }; ' Return dataList; '} ' Method to process each data item and return the result (replace with your actual data processing logic) 'INSTANT VB TODO TASK: Local functions are not converted by Instant VB: 'string ProcessDataItem(DataItem dataItem) '{ ' ' Simulating data processing with a delay ' Task.Delay(100).Wait(); ' Return string.Format("Processed: {0}", dataItem.Name); '} ' Method to build the HTML report using the processed data (replace with your actual reporting logic) 'INSTANT VB TODO TASK: Local functions are not converted by Instant VB: 'string BuildHtmlReport(ConcurrentDictionary(Of int, string) processedData) '{ ' string html = "<h1>Processed Data Report</h1><ul>"; ' foreach (var kvp in processedData) ' { ' html += string.Format("<li>Item {0}: {1}</li>", kvp.Key, kvp.Value); ' } ' html += "</ul>"; ' Return html; '} ' Placeholder class for your data item (replace with your actual data item class) 'INSTANT VB TODO TASK: Local functions are not converted by Instant VB: 'public class DataItem '{ ' public int Id ' { ' get; ' set; ' } ' public string Name ' { ' get; ' set; ' } ' ' Add other properties as needed '} $vbLabelText $csharpLabel 以下是程式碼的輸出: 結論 總而言之,瞭解並運用 C# 並發集合(例如並發清單),可以大幅提升您處理多執行緒情境的能力,並確保應用程式中的線程安全。 使用並發集合,您可以有效地管理共用資源,防止資料競賽和線程間的碰撞。 整合 IronPDF 之類的外部函式庫,可以藉由產生視覺上吸引人的 PDF 報告或文件,進一步強化並發集合的功能。 IronPdf 提供 免費試用其 HTML 至 PDF 轉換函式庫,讓您探索其功能,以及 $799 起的授權選項。 常見問題解答 什麼是 C# 中的並發集合? C# 中的並發集合是一套線程安全的通用集合類別,可在多個線程存取共用資源時確保線程安全。 為什麼線程安全在 C# 中很重要? 線程安全在 C# 中非常重要,可防止多個線程同時存取和修改共用資源時發生混亂和資料損毀。它可確保操作以受控的方式執行。 如何在 C# 中建立線程安全列表? 雖然 C# 沒有直接提供線程安全的 List 類別,但您可以使用其他並發集合,例如 `ConcurrentBag` 或 `ConcurrentDictionary` 來進行類似的線程安全操作。 什麼是 C# 中的 ConcurrentDictionary? C# 中的 ConcurrentDictionary 是 `System.Collections.Concurrent` 命名空間中的線程安全集合類別。它允許多個線程同時安全地新增、更新及移除鍵值對。 ConcurrentDictionary 如何確保線程安全? ConcurrentDictionary 透過內部同步處理來確保線程安全,一次只允許一個線程執行新增或移除項目等作業。 如何將項目新增至 ConcurrentDictionary? 您可以使用 TryAdd 方法將項目新增至 ConcurrentDictionary,此方法僅會在詞典中尚未存在鍵值對時嘗試新增該鍵值對。 並發集合中 CopyTo 方法的目的是什麼? 並發集合中的 CopyTo 方法用來將集合中的元素複製到陣列中,提供將資料從集合傳輸到另一種儲存格式的方法。 IronPDF 可以用來從處理過的資料產生 PDF 報告嗎? 是的,IronPDF 可用於從多執行緒應用程式所處理的資料中產生 PDF 報告,捕捉並發作業的結果。 使用 IronPDF 如何增強並發操作的功能? IronPdf 透過從處理過的資料建立 PDF 文件來增強並發作業,提供一種記錄和分享多執行緒處理結果的方式。 IronPDF 在多線程 C# 應用程式中扮演什麼角色? IronPDF 可讓開發人員從平行處理的資料中產生 PDF 報告,讓多執行緒作業的結果更容易整合與分享。 Jacob Mellor 立即與工程團隊聊天 首席技术官 Jacob Mellor 是 Iron Software 的首席技術官,作為 C# PDF 技術的先鋒工程師。作為 Iron Software 核心代碼的原作者,他自開始以來塑造了公司產品架構,與 CEO Cameron Rimington 一起將其轉變為一家擁有超過 50 名員工的公司,為 NASA、特斯拉 和 全世界政府機構服務。Jacob 持有曼徹斯特大學土木工程一級榮譽学士工程學位(BEng) (1998-2001)。他於 1999 年在倫敦開設了他的第一家軟件公司,並於 2005 年製作了他的首個 .NET 組件,專注於解決 Microsoft 生態系統內的複雜問題。他的旗艦產品 IronPDF & Iron Suite .NET 庫在全球 NuGet 被安裝超過 3000 萬次,其基礎代碼繼續為世界各地的開發工具提供動力。擁有 25 年的商業經驗和 41 年的編碼專業知識,Jacob 仍專注於推動企業級 C#、Java 及 Python PDF 技術的創新,同時指導新一代技術領袖。 相關文章 更新12月 11, 2025 銜接 CLI 簡化與 .NET : 使用 Curl DotNet 與 IronPDF for .NET Jacob Mellor 藉由 CurlDotNet 彌補了這方面的不足,CurlDotNet 是為了讓 .NET 生態系統能熟悉 cURL 而建立的函式庫。 閱讀更多 更新9月 4, 2025 RandomNumberGenerator C# 使用RandomNumberGenerator C#類可以幫助將您的PDF生成和編輯項目提升至新水準 閱讀更多 更新9月 4, 2025 C#字符串等於(它如何對開發者起作用) 當結合使用強大的PDF庫IronPDF時,開關模式匹配可以讓您構建更智能、更清晰的邏輯來進行文檔處理 閱讀更多 什麼是 Visual Studio(開發者的工作原理)Windows Vim(開發者的工作原...
更新12月 11, 2025 銜接 CLI 簡化與 .NET : 使用 Curl DotNet 與 IronPDF for .NET Jacob Mellor 藉由 CurlDotNet 彌補了這方面的不足,CurlDotNet 是為了讓 .NET 生態系統能熟悉 cURL 而建立的函式庫。 閱讀更多