跳過到頁腳內容
.NET幫助

C# 並發列表(開發者的工作原理)

如果您曾經遇到多個執行緒爭相存取共享資源的情況,您就會知道執行緒安全實現不是遊戲。 不過,請放心! C#提供了並發集合 - 一個強大的執行緒安全泛型集合類別套件,確保執行緒的安全性,並且做到風格和優雅。

Thread Safety and Concurrent Collections in C#

讓我們先想像一下繁忙的城市路口,沒有交通燈。 您可以想像這種混亂! 這類似於當多個執行緒同時存取共享資源但沒有適當系統的情況。 幸運的是,在C#中,我們有了控制執行緒的交通燈-它們稱為並發集合。 它們是集合類別,只允許一個執行緒同時存取資源。這在處理多個執行緒時,執行緒安全至關重要。

Exploring Concurrent Thread Safe Collections in C#

在C#中,namespace System.Collections.Concurrent 擁有各種並發集合類別,例如 ConcurrentStackConcurrentBag。 這些無序集合類別提供了其非並發對應項的執行緒安全版本。 並發集合的特點是它們是無序並發集合,這意味著元素沒有特定的順序。 例如,使用並發列表時,您不能確定一項是插入在哪裡。 重點是確保執行緒安全,而不是保持順序。

讓我們舉一個現實生活的例子。 想像一下網站上的密碼提交帖子。使用並發集合,複數用戶可以同時提交他們的密碼。 每個"提交"動作就像一個執行緒,並發集合確保每個提交都是執行緒安全的,處理時既安全又有效。

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>();
$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);
}
$vbLabelText   $csharpLabel

在這種情境下,ConcurrentDictionary 集合類別 確保每次點擊(或"執行緒")都單獨處理,因此不會有兩個用戶的推薦內容混在一起。它處理了所有執行緒安全問題,讓您不必擔心資料競賽和其他與多個執行緒相關的併發問題。

實現執行緒安全操作

除了 TryAdd,C#中的並發集合還提供了各種其他執行緒安全操作,例如 TryRemoveTryUpdate。 這些方法確保只有一個執行緒可以一次執行一個操作。因此,例如,如果我們想從上一個例子中的用戶推薦中移除一本書,我們可以使用 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);
}
$vbLabelText   $csharpLabel

TryRemove 方法將嘗試移除提供的金鑰的值(在這種情況下,為用戶),並將其放入 removedBook 變數中。

複製並發集合

現在,假設您希望將並發集合複製到一個陣列中。 並發集合為此提供了一個 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);
}
$vbLabelText   $csharpLabel

這裡,CopyTo 方法將所有書籍(值)從 recommendedBooks 並發字典中複製到 bookArray 中。

執行緒安全集合

C#還提供了執行緒安全集合,它們設計來確保在多執行緒環境中安全存取共享資源。 這些集合如 ConcurrentQueueConcurrentStack 提供了執行緒安全實現,多個執行緒可以同時連接和修改集合而不會造成衝突或資料損壞。

它們透過內部同步來保證一致性和完整性,從而成為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");
    }
}
$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
}
$vbLabelText   $csharpLabel

這是程式碼的輸出:

C#並發列表(它如何為開發者工作)圖1 - 輸出

結論

總而言之,了解並運用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, 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技術的創新,同時指導下一代技術領導者。

Iron Support Team

We're online 24 hours, 5 days a week.
Chat
Email
Call Me