Test in einer Live-Umgebung
Test in der Produktion ohne Wasserzeichen.
Funktioniert überall, wo Sie es brauchen.
Wenn Sie schon einmal mehrere Threads hatten, die sich um den Zugriff auf eine gemeinsame Ressource stritten, wissen Sie, dass eine thread-sichere Implementierung kein Spiel ist. Aber keine Sorge! C# bietet Ihnen mit Concurrent Collections eine leistungsstarke Reihe von thread-sicheren, generischen Collection-Klassen, die Thread-Sicherheit mit Stil und Anmut gewährleisten.
Stellen wir uns zunächst eine belebte Stadtkreuzung ohne Ampeln vor. Sie können sich das Chaos vorstellen! Dies ist vergleichbar mit dem, was passiert, wenn mehrere Threads gleichzeitig auf eine gemeinsame Ressource zugreifen, ohne dass ein geeignetes System vorhanden ist. Zum Glück gibt es in C# Ampeln für unsere Threads - diese werden als Concurrent Collections bezeichnet. Es handelt sich um Auflistungsklassen, die jeweils nur einem Thread den Zugriff auf eine Ressource erlauben. Diese Thread-Sicherheit ist entscheidend, wenn man mit mehreren Threads arbeitet.
In C# enthält der Namespace System.Collections.Concurrent
eine Vielzahl von Klassen für gleichzeitige Sammlungen, wie ConcurrentDictionary
, ConcurrentQueue
, ConcurrentStack
und ConcurrentBag
. Diese ungeordneten Auflistungsklassen bieten eine thread-sichere Version ihrer nicht-konkurrierenden Gegenstücke. Gleichzeitige Sammlungen zeichnen sich dadurch aus, dass sie ungeordnet sind, d. h. die Elemente haben keine bestimmte Reihenfolge. Bei einer gleichzeitigen Liste wissen Sie beispielsweise nicht genau, wo ein Element eingefügt wird. Der Schwerpunkt liegt auf der Gewährleistung der Fadensicherheit und nicht auf der Aufrechterhaltung einer Ordnung.
Nehmen wir ein Beispiel aus der Praxis. Stellen Sie sich eine Kennwortübermittlung auf einer Website vor. Bei einer gleichzeitigen Erfassung können mehrere Benutzer ihre Kennwörter gleichzeitig übermitteln. Jede "Submit"-Aktion ist wie ein Thread, und die Concurrent Collection stellt sicher, dass jede Übermittlung thread-sicher ist und sicher und effektiv verarbeitet wird.
Lassen Sie uns nun die Sammelklasse "ConcurrentDictionary" anhand eines praktischen Beispiels untersuchen. Stellen Sie sich eine Online-Buchhandlung mit einer Empfehlungsfunktion vor. Jeder Klick des Nutzers fügt ein Buch zu seiner persönlichen Empfehlungsliste hinzu, die durch ein Wörterbuch dargestellt wird. Da mehrere Benutzer gleichzeitig Bücher durchsuchen und anklicken, greifen mehrere Threads gleichzeitig auf das Wörterbuch zu.
Ein ConcurrentDictionary
in C# würde etwa so aussehen:
ConcurrentDictionary<string, string> recommendedBooks = new ConcurrentDictionary<string, string>();
ConcurrentDictionary<string, string> recommendedBooks = new ConcurrentDictionary<string, string>();
Dim recommendedBooks As New ConcurrentDictionary(Of String, String)()
Um ein Buch zur gesamten Empfehlungssammlung eines Benutzers hinzuzufügen, können wir die Methode "Insert" verwenden:
public void Insert(string user, string book)
{
recommendedBooks.TryAdd(user, book);
}
public void Insert(string user, string book)
{
recommendedBooks.TryAdd(user, book);
}
Public Sub Insert(ByVal user As String, ByVal book As String)
recommendedBooks.TryAdd(user, book)
End Sub
In diesem Szenario sorgt die Sammelklasse ConcurrentDictionary
dafür, dass jeder Klick(oder 'Gewinde') werden einzeln behandelt, so dass die Empfehlungen von zwei Benutzern nicht durcheinander geraten. Es übernimmt die gesamte Thread-Sicherheit, so dass Sie sich keine Sorgen über Data Races und andere Gleichzeitigkeitsprobleme im Zusammenhang mit mehreren Threads machen müssen.
Neben TryAdd
bieten Concurrent Collections in C# eine Vielzahl anderer Thread-sicherer Operationen wie TryRemove
und TryUpdate
. Diese Methoden stellen sicher, dass jeweils nur ein Thread einen Vorgang ausführen kann. Wenn wir also zum Beispiel im vorherigen Beispiel ein Buch aus den Empfehlungen eines Benutzers entfernen wollten, könnten wir die Methode TryRemove
verwenden:
public void RemoveAt(string user)
{
string removedBook;
recommendedBooks.TryRemove(user, out removedBook);
}
public void RemoveAt(string user)
{
string removedBook;
recommendedBooks.TryRemove(user, out removedBook);
}
Public Sub RemoveAt(ByVal user As String)
Dim removedBook As String = Nothing
recommendedBooks.TryRemove(user, removedBook)
End Sub
Die Methode TryRemove
versucht, den Wert des angegebenen Schlüssels zu entfernen(in diesem Fall, ein Benutzer) und setzen Sie es in die Variable removedBook
.
Nehmen wir nun an, Sie möchten Ihre gleichzeitige Sammlung in ein Array kopieren. Gleichzeitige Sammlungen bieten eine "CopyTo"-Methode für genau diesen Zweck:
public void CopyTo()
{
string[] bookArray = new string[recommendedBooks.Count];
recommendedBooks.Values.CopyTo(bookArray, 0);
}
public void CopyTo()
{
string[] bookArray = new string[recommendedBooks.Count];
recommendedBooks.Values.CopyTo(bookArray, 0);
}
Public Sub CopyTo()
Dim bookArray(recommendedBooks.Count - 1) As String
recommendedBooks.Values.CopyTo(bookArray, 0)
End Sub
Hier kopiert die Methode CopyTo
alle Bücher(werte) aus dem konkurrierenden Wörterbuch empfohleneBücher
in das bookArray
.
C# bietet außerdemthread-sichere Sammlungendie den sicheren Zugang zu gemeinsamen Ressourcen in Multithreading-Umgebungen gewährleisten sollen. Diese Sammlungen, wie ConcurrentBag
, ConcurrentQueue
und ConcurrentStack
, bieten Thread-sichere Implementierungen, bei denen mehrere Threads gleichzeitig auf die Sammlung zugreifen und sie ändern können, ohne Konflikte oder Datenverfälschungen zu verursachen.
Sie garantieren Konsistenz und Integrität, indem sie die Synchronisierung intern handhaben. Das macht sie ideal für Szenarien, in denen eine ungeordnete Auflistung ausreicht und die Threadsicherheit in Ihren C#-Anwendungen von größter Bedeutung ist.
Erfahren Sie mehr über IronPDF ist eine beliebte C#-Bibliothek, mit der SiepDF-Dokumente mühelos aus HTML generieren.
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
Auch wenn es auf den ersten Blick nicht direkt mit Concurrent-Listen zusammenhängt, kann IronPDF Ihre Concurrent-Collection-Vorgänge ergänzen, indem es eine einfache Möglichkeit zur Erstellung von PDF-Berichten, Protokollen oder anderen Dokumenten bietet, in denen die Ergebnisse Ihrer Concurrent-Verarbeitung festgehalten werden.
Stellen Sie sich ein Szenario vor, in dem Sie eine Multithreading-Anwendung haben, die eine intensive Datenverarbeitung durchführt. Während die Threads die Daten bearbeiten, können Sie die Ergebnisse erfassen und einen PDF-Bericht für weitere Analysen oder Aufzeichnungen erstellen. An dieser Stelle kommt IronPDF ins Spiel.
Die Verwendung von IronPDF ist so einfach wie das Hinzufügen der Bibliothek zu Ihrem Projekt und die Nutzung ihrer praktischen API. Hier ist ein Beispiel dafür, wie Sie IronPDF in Ihre gleichzeitigen Erfassungsvorgänge integrieren können:
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) =>
{
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) =>
{
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)
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
'}
Hier ist die Ausgabe des Codes:
Zusammenfassend lässt sich sagen, dass das Verständnis und die Verwendung von C# Concurrent Collections, wie z. B. Concurrent Lists, Ihre Fähigkeit, Multi-Threading-Szenarien zu handhaben und die Thread-Sicherheit in Ihren Anwendungen zu gewährleisten, erheblich verbessern kann. Mit konkurrierenden Sammlungen können Sie gemeinsam genutzte Ressourcen effektiv verwalten und Datenüberschneidungen und Kollisionen zwischen Threads verhindern.
Die Integration externer Bibliotheken wie IronPDF kann die Funktionalität gleichzeitiger Sammlungen durch die Erstellung visuell ansprechender PDF-Berichte oder -Dokumente noch erweitern. IronPDF bietet einekostenlose Testversion der Bibliothek für die Konvertierung von HTML in PDFdie es Ihnen ermöglicht, seine Fähigkeiten zu erkunden, und Lizenzoptionen ab $749.
9 .NET API-Produkte für Ihre Bürodokumente