
C# 并发列表(开发者如何使用)
如果您曾经遇到过多个线程争夺对共享资源的访问权,您就知道线程安全的实现不是游戏。 不过不用担心! C# 提供了并发集合 - 一套强大的线程安全泛型集合类,以优雅的方式确保线程安全。
Thread Safety and Concurrent Collections in C#
让我们从设想一个繁忙的城市十字路口开始,没有交通灯。 您可以想象那种混乱! 本指南探讨 C# 并发集合如何在多线程场景中实现线程安全操作,避免共享资源访问冲突,并演示 ConcurrentDictionary 与 IronPDF 的集成应用。 幸运的是,在 C# 中,我们有线程的交通灯 - 这些称为并发集合。 它们是集合类,仅允许一个线程在同一时间访问资源。这种线程安全在处理多个线程时至关重要。
Exploring Concurrent Thread Safe Collections in C#
在C#中,命名空间ConcurrentBag。 这些无序集合类提供了它们的非并发版本的线程安全版本。 使并发集合与众不同的是,它们是无序的并发集合,意味着元素没有特定的顺序。 例如,在并发列表中,您不知道一个项插入的确切位置。 重点是确保线程安全,而不是保持顺序。
让我们看一个真实的例子。 想象一下一个网站上的密码提交帖子。使用并发集合,多个用户可以同时提交他们的密码。 每个"提交"操作就像一个线程,并发集合确保每次提交都是线程安全的,坚持处理安全有效。
ConcurrentDictionary:一个真实世界的例子
现在,让我们通过一个实际例子来探索ConcurrentDictionary集合类。 想象一个具有推荐功能的在线书店。 每个用户的点击都会向他们的个人推荐列表中添加一本书,由字典表示。 随着多个用户同时浏览和点击书籍,我们有多个线程同时访问字典。
在C#中,ConcurrentDictionary看起来会像这样:
using System.Collections.Concurrent;
ConcurrentDictionary<string, string> recommendedBooks = new ConcurrentDictionary<string, string>();Imports System.Collections.Concurrent
Private recommendedBooks As New ConcurrentDictionary(Of String, String)()要将一本书添加到用户的推荐收藏中,我们可以使用TryAdd方法:
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在这种情况下,ConcurrentDictionary集合类确保每一次点击(或"线程")都单独处理,因此不会混淆不同用户的推荐。它处理所有线程安全问题,因此您不必担心数据竞争和其他与多线程相关的并发问题。
实现线程安全操作
除了TryUpdate。 这些方法确保一次只有一个线程可以执行操作。因此,例如,如果我们想在前面的示例中从用户的推荐中删除一本书,我们可以使用TryRemove方法:
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 SubremovedBook变量中。
复制并发集合
现在,假设您想将并发集合复制到一个数组。 并发集合为此提供了一个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 Sub CopyTo()
' Create an array to hold the recommended books
Dim bookArray As String() = New String(recommendedBooks.Count - 1) {}
' Copy the values of the concurrent dictionary to the array
recommendedBooks.Values.CopyTo(bookArray, 0)
End Sub此处,bookArray中。
线程安全集合
C# 还提供了 线程安全集合,专为确保在多线程环境中安全访问共享资源而设计。 这些集合,如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");
}
}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虽然乍一看,它似乎与并发列表没有直接关系,但 IronPDF 可以通过提供一种轻松创建 PDF 报告、日志或捕捉并发处理结果其他文档的方法来补充您的并发集合操作。
考虑一个执行密集型数据处理的多线程应用程序场景。 当线程在数据上进行操作时,您可能打算捕获结果并生成 PDF 报告以进行进一步分析或记录。 这正是 IronPDF 发挥作用的地方。 using 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
}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
'}以下是代码的输出:

结论
总之,理解并使用 C# 并发集合,如并发列表,可以极大地提升您在多线程环境中处理场景的能力,并确保应用程序中的线程安全。 使用并发集合,您可以有效管理共享资源,防止线程间的数据竞争和冲突。
集成像 IronPDF 这样的外部库还可以通过生成具有视觉吸引力的 PDF 报告或文档来进一步增强并发集合的功能。 IronPDF提供了其库的免费试用版用于HTML到PDF转换,允许您探索其功能,以及从$999开始的许可证选项。

Jacob Mellor 是 Iron Software 的首席技术官,也是一位开创 C# PDF 技术的有远见的工程师。作为 Iron Software 核心代码库的原始开发者,他从公司成立之初就开始塑造公司的产品架构,与首席执行官 Cameron Rimington 一起将公司转变为一家拥有 50 多名员工的公司,为 NASA、特斯拉和全球政府机构提供服务。
相关文章


