.NET-HILFE

C# Semaphoreslim (Wie es für Entwickler funktioniert)

Veröffentlicht 23. Oktober 2024
Teilen Sie:

Einführung

Die Gleichzeitigkeitsverwaltung ist ein wichtiger Aspekt von Hochleistungsanwendungen in C#. Sie stellt sicher, dass die Ressourcen effizient genutzt werden und gleichzeitig potenzielle Konflikte oder Leistungsengpässe vermieden werden, weshalb eine leichtgewichtige Semaphore, die den Zugriff steuert, sehr hilfreich sein kann. Dies ist der Ort, an demSemaphoreSlim ins Spiel kommt. SemaphoreSlim ist ein leichtgewichtiges Synchronisationsprimitiv, das den Ressourcenzugriff steuert und letztlich Race Conditions verhindert und Threadsicherheit gewährleistet.

Was wäre, wenn Sie dies zusammen mit einer PDF-Bibliothek zur Verwaltung von PDF-Erzeugungsprozessen implementieren wollten? Vielleicht suchen Sie eine leistungsfähige PDF-Bibliothek, in derIronPDF kommt herein. IronPDF ist eine robuste Bibliothek zur PDF-Erzeugung und -Bearbeitung für .NET-Entwickler, die bei der Verwendung in Multithreading-Umgebungen stark von der Gleichzeitigkeitsverwaltung profitieren kann.

Wenn Sie SemaphoreSlim und IronPDF in Aktion sehen möchten, lesen Sie bitte weiter, um die Vorteile von SemaphoreSlim kennenzulernen und zu erfahren, wie es in IronPDF integriert werden kann, um gleichzeitige Operationen sicher zu handhaben, die Leistung zu verbessern und eine zuverlässige PDF-Verarbeitung zu gewährleisten.

SemaphoreSlim in C&num verstehen

Was ist SemaphoreSlim?

SemaphoreSlim ist ein Synchronisationsprimitiv in .NET, das die Anzahl der Threads begrenzt, die gleichzeitig auf eine bestimmte Ressource oder einen Pool von Ressourcen zugreifen können. Es handelt sich um eine abgespeckte Version der vollständigen Semaphore-Klasse, die in Situationen, in denen ein einfacheres, schnelleres Semaphore ausreicht, effizienter arbeiten soll.

Einige Vorteile der Verwendung von SemaphoreSlim sind, dass der System-Overhead im Vergleich zu Semaphore reduziert ist, es ist ideal für die Verwaltung begrenzter Ressourcen(wie z. B. Datenbankverbindungen oder Dateizugriff)es unterstützt asynchrone Warteverfahren und eignet sich daher gut für moderne Async/Await-Programmiermuster.

Code-Beispiel für die grundlegende Verwendung von SemaphoreSlim

using System;
using System.Threading;
using System.Threading.Tasks;
class program
{
    // Semaphore count
    private static SemaphoreSlim semaphore = new SemaphoreSlim(3); // Limit to 3 concurrent threads.
    static async Task Main(string[] args)
    {
        // Start tasks that will wait on the semaphore.
        var tasks = new Task[5];
        for (int i = 0; i < tasks.Length; i++)
        {
            tasks[i] = Task.Run(() => AccessResource(i));
        }
        // Simulate some work in the main thread (e.g., initialization).
        Console.WriteLine("Main thread is preparing resources...");
        await Task.Delay(2000);  // Simulate initialization delay.
        // main thread calls release, releases semaphore permits to allow waiting tasks to proceed.
        Console.WriteLine("Main thread releasing semaphore permits...");
        semaphore.Release(2);  // Releases 2 permits, allowing up to 2 tasks to proceed.
        // Wait for all tasks to complete.
        await Task.WhenAll(tasks);
        Console.WriteLine("All tasks completed.");
    }
    static async Task AccessResource(int id)
    {
        Console.WriteLine($"Task {id} waiting to enter...");
        await _semaphore.WaitAsync();
        try
        {
            Console.WriteLine($"current thread successfully entered by Task {id} .");
            await Task.Delay(1000); // Simulate work.
        }
        finally
        {
            Console.WriteLine($"Task {id} releasing.");
            _semaphore.Release();
        }
    }
}
using System;
using System.Threading;
using System.Threading.Tasks;
class program
{
    // Semaphore count
    private static SemaphoreSlim semaphore = new SemaphoreSlim(3); // Limit to 3 concurrent threads.
    static async Task Main(string[] args)
    {
        // Start tasks that will wait on the semaphore.
        var tasks = new Task[5];
        for (int i = 0; i < tasks.Length; i++)
        {
            tasks[i] = Task.Run(() => AccessResource(i));
        }
        // Simulate some work in the main thread (e.g., initialization).
        Console.WriteLine("Main thread is preparing resources...");
        await Task.Delay(2000);  // Simulate initialization delay.
        // main thread calls release, releases semaphore permits to allow waiting tasks to proceed.
        Console.WriteLine("Main thread releasing semaphore permits...");
        semaphore.Release(2);  // Releases 2 permits, allowing up to 2 tasks to proceed.
        // Wait for all tasks to complete.
        await Task.WhenAll(tasks);
        Console.WriteLine("All tasks completed.");
    }
    static async Task AccessResource(int id)
    {
        Console.WriteLine($"Task {id} waiting to enter...");
        await _semaphore.WaitAsync();
        try
        {
            Console.WriteLine($"current thread successfully entered by Task {id} .");
            await Task.Delay(1000); // Simulate work.
        }
        finally
        {
            Console.WriteLine($"Task {id} releasing.");
            _semaphore.Release();
        }
    }
}
Imports System
Imports System.Threading
Imports System.Threading.Tasks
Friend Class program
	' Semaphore count
	Private Shared semaphore As New SemaphoreSlim(3) ' Limit to 3 concurrent threads.
	Shared Async Function Main(ByVal args() As String) As Task
		' Start tasks that will wait on the semaphore.
		Dim tasks = New Task(4){}
		For i As Integer = 0 To tasks.Length - 1
			tasks(i) = Task.Run(Function() AccessResource(i))
		Next i
		' Simulate some work in the main thread (e.g., initialization).
		Console.WriteLine("Main thread is preparing resources...")
		Await Task.Delay(2000) ' Simulate initialization delay.
		' main thread calls release, releases semaphore permits to allow waiting tasks to proceed.
		Console.WriteLine("Main thread releasing semaphore permits...")
		semaphore.Release(2) ' Releases 2 permits, allowing up to 2 tasks to proceed.
		' Wait for all tasks to complete.
		Await Task.WhenAll(tasks)
		Console.WriteLine("All tasks completed.")
	End Function
	Private Shared Async Function AccessResource(ByVal id As Integer) As Task
		Console.WriteLine($"Task {id} waiting to enter...")
		Await _semaphore.WaitAsync()
		Try
			Console.WriteLine($"current thread successfully entered by Task {id} .")
			Await Task.Delay(1000) ' Simulate work.
		Finally
			Console.WriteLine($"Task {id} releasing.")
			_semaphore.Release()
		End Try
	End Function
End Class
VB   C#

Während des Betriebs eines Programms kann die Anzahl der Semaphoren dynamisch null Threads erreichen, wenn alle verfügbaren Genehmigungen von Threads erworben wurden. Dieser Zustand zeigt an, dass die maximal zulässigen gleichzeitigen Zugriffe erreicht wurden.

Wenn Sie möchten, können Sie die anfängliche und maximale Anzahl von Threads festlegen, indem Sie die anfängliche Semaphorenzahl auf Null setzen und dann eine separate Initialisierungsaufgabe verwenden, die die Semaphorenzahl erhöht, wenn die Ressource bereit ist, so dass die von Ihnen gewählte Anzahl von Threads fortgesetzt werden kann. Wenn die Anzahl der Semaphoren gleich Null ist, warten die Threads, wenn sie versuchen, die Semaphoren zu betreten, was als "block waiting" bezeichnet wird.

Sie könnten den vorherigen Semaphorenzähler verfolgen, um das Verhalten des Semaphors auf der Grundlage des vorherigen Zählers anzupassen, Sie können dann den Semaphor entsprechend manipulieren(z. B. durch Freigeben oder Warten). Wenn die Threads freigegeben werden, wird die Anzahl der Semaphore verringert.

Konsolenausgabe

C# Semaphoreslim(Wie es für Entwickler funktioniert): Abbildung 1

Häufige Anwendungsfälle für SemaphoreSlim

Einige häufige Anwendungsfälle für SemaphoreSlim sind:

  • Beschränkung des Zugriffs auf Datenbanken oder Dateisysteme: Sie verhindert, dass diese Ressourcen durch zu viele gleichzeitige Anfragen überlastet werden.
  • Verwaltung von Thread-Pools: Es kann verwendet werden, um die Anzahl der Threads zu kontrollieren, die eine bestimmte Operation ausführen, und so die Stabilität und Leistung zu verbessern.

Verwendung von SemaphoreSlim mit IronPDF für sichere Gleichzeitigkeit

Einrichten von IronPDF in einer Multi-Threaded-Umgebung

Um IronPDF in einer Multithreading-Umgebung zu verwenden, installieren Sie zunächst dieIronPDF NuGet-Paket. Navigieren Sie dazu zu tools > NuGet Package Manager > NuGet Package Manager for Solution und suchen Sie IronPDF:

C# Semaphoreslim(Wie es für Entwickler funktioniert): Abbildung 2

Oder führen Sie alternativ den folgenden Befehl in der Paketmanager-Konsole aus:

Install-Package IronPdf
Install-Package IronPdf
'INSTANT VB TODO TASK: The following line uses invalid syntax:
'Install-Package IronPdf
VB   C#

Um IronPDF in Ihrem Code zu verwenden, stellen Sie sicher, dass Sie die Anweisung `using IronPdf` am Anfang Ihrer Codedatei platziert haben. Eine ausführlichere Anleitung zur Einrichtung von IronPDF in Ihrer Umgebung finden Sie in dererste Schritte seite.

Zugriffskontrolle bei der PDF-Erzeugung mit SemaphoreSlim

Wenn Sie SemaphoreSlim verwenden, können Sie den Zugriff auf PDF-Generierungsaufgaben effektiv steuern. Dadurch wird sichergestellt, dass Ihre Anwendung nicht versucht, zu viele PDFs gleichzeitig zu erzeugen, was die Leistung beeinträchtigen oder zu Fehlern führen könnte.

Der folgende Beispielcode demonstriert die grundlegende Verwendung von SemaphoreSlim mit IronPDF.

using IronPdf;
using System;
using System.Threading;
using System.Threading.Tasks;
using IronPdf.Exceptions;
using System.Net.Http;
using System.Runtime.CompilerServices;
class program
{
    private static SemaphoreSlim _semaphore = new SemaphoreSlim(2); // Limit to 2 concurrent threads.
    static async Task Main(string[] args)
    {
        var tasks = new Task[5];
        for (int i = 0; i < tasks.Length; i++)
        {
            string htmlContent = $"<h1>PDF Document {i}</h1><p>This is a sample PDF content for task {i}.</p>";
            string outputPath = $"output_{i}.pdf";
            // Start multiple tasks to demonstrate controlled concurrency.
            tasks[i] = GeneratePdfAsync(htmlContent, outputPath, i);
        }
        await Task.WhenAll(tasks);
    }
    static async Task GeneratePdfAsync(string htmlContent, string outputPath, int taskId)
    {
        Console.WriteLine($"Task {taskId} is waiting for access...");
        // Wait to enter the semaphore.
        await _semaphore.WaitAsync();
        try
        {
            Console.WriteLine($"Task {taskId} has started PDF generation.");
            ChromePdfRenderer renderer = new ChromePdfRenderer();
            PdfDocument pdf = await renderer.RenderHtmlAsPdfAsync(htmlContent);
            pdf.SaveAs(outputPath);
            Console.WriteLine($"Task {taskId} has completed PDF generation.");
        }
        finally
        {
            // Ensure semaphore is released to allow other tasks to proceed.
            _semaphore.Release();
            Console.WriteLine($"Task {taskId} has released semaphore.");
        }
    }
}
using IronPdf;
using System;
using System.Threading;
using System.Threading.Tasks;
using IronPdf.Exceptions;
using System.Net.Http;
using System.Runtime.CompilerServices;
class program
{
    private static SemaphoreSlim _semaphore = new SemaphoreSlim(2); // Limit to 2 concurrent threads.
    static async Task Main(string[] args)
    {
        var tasks = new Task[5];
        for (int i = 0; i < tasks.Length; i++)
        {
            string htmlContent = $"<h1>PDF Document {i}</h1><p>This is a sample PDF content for task {i}.</p>";
            string outputPath = $"output_{i}.pdf";
            // Start multiple tasks to demonstrate controlled concurrency.
            tasks[i] = GeneratePdfAsync(htmlContent, outputPath, i);
        }
        await Task.WhenAll(tasks);
    }
    static async Task GeneratePdfAsync(string htmlContent, string outputPath, int taskId)
    {
        Console.WriteLine($"Task {taskId} is waiting for access...");
        // Wait to enter the semaphore.
        await _semaphore.WaitAsync();
        try
        {
            Console.WriteLine($"Task {taskId} has started PDF generation.");
            ChromePdfRenderer renderer = new ChromePdfRenderer();
            PdfDocument pdf = await renderer.RenderHtmlAsPdfAsync(htmlContent);
            pdf.SaveAs(outputPath);
            Console.WriteLine($"Task {taskId} has completed PDF generation.");
        }
        finally
        {
            // Ensure semaphore is released to allow other tasks to proceed.
            _semaphore.Release();
            Console.WriteLine($"Task {taskId} has released semaphore.");
        }
    }
}
Imports IronPdf
Imports System
Imports System.Threading
Imports System.Threading.Tasks
Imports IronPdf.Exceptions
Imports System.Net.Http
Imports System.Runtime.CompilerServices
Friend Class program
	Private Shared _semaphore As New SemaphoreSlim(2) ' Limit to 2 concurrent threads.
	Shared Async Function Main(ByVal args() As String) As Task
		Dim tasks = New Task(4){}
		For i As Integer = 0 To tasks.Length - 1
			Dim htmlContent As String = $"<h1>PDF Document {i}</h1><p>This is a sample PDF content for task {i}.</p>"
			Dim outputPath As String = $"output_{i}.pdf"
			' Start multiple tasks to demonstrate controlled concurrency.
			tasks(i) = GeneratePdfAsync(htmlContent, outputPath, i)
		Next i
		Await Task.WhenAll(tasks)
	End Function
	Private Shared Async Function GeneratePdfAsync(ByVal htmlContent As String, ByVal outputPath As String, ByVal taskId As Integer) As Task
		Console.WriteLine($"Task {taskId} is waiting for access...")
		' Wait to enter the semaphore.
		Await _semaphore.WaitAsync()
		Try
			Console.WriteLine($"Task {taskId} has started PDF generation.")
			Dim renderer As New ChromePdfRenderer()
			Dim pdf As PdfDocument = Await renderer.RenderHtmlAsPdfAsync(htmlContent)
			pdf.SaveAs(outputPath)
			Console.WriteLine($"Task {taskId} has completed PDF generation.")
		Finally
			' Ensure semaphore is released to allow other tasks to proceed.
			_semaphore.Release()
			Console.WriteLine($"Task {taskId} has released semaphore.")
		End Try
	End Function
End Class
VB   C#

In diesem Beispiel haben wir zunächst SemaphoreSlim initialisiert und die anfängliche und maximale Anzahl von SemaphoreSlim auf "2" gesetzt, um es auf zwei gleichzeitige PDF-Generationen zu beschränken. Anschließend haben wir ein Aufgaben-Array erstellt, das zur Steuerung der Anzahl der Aufgaben dient, die das Programm zu erledigen hat. Danach verwenden wir eine for-Schleife, um dynamisch PDFs auf der Grundlage der Anzahl der Aufgaben innerhalb des Aufgaben-Arrays zu erstellen.

Die `WaitAsync()\Die Methode "" wird dann verwendet, um das Semaphor einzugeben, und "" Release()`** wird im finally-Block verwendet, um sicherzustellen, dass die Semaphore immer freigegeben wird, auch wenn eine Ausnahme auftritt. Die Konsolenausgabeprotokolle zeigen an, wann jede Aufgabe beginnt, endet und die Semaphore freigibt, so dass Sie das Gleichzeitigkeitsverhalten verfolgen können.

Ausgabekonsole

C# Semaphoreslim(Wie es für Entwickler funktioniert): Abbildung 3

PDF-Dateien ausgeben

C# Semaphoreslim(Wie es für Entwickler funktioniert): Abbildung 4

Gewährleistung der Thread-Sicherheit bei PDF-Manipulationsvorgängen

Thread-Sicherheit ist entscheidend, wenn mehrere Threads mit gemeinsamen Ressourcen interagieren. Bei der PDF-Bearbeitung sorgt SemaphoreSlim dafür, dass nur eine bestimmte Anzahl von Threads gleichzeitig PDFs ändern kann, wodurch Race Conditions verhindert und die Konsistenz sichergestellt wird. Im folgenden Code simulieren wir ein Szenario, in dem wir ein Wasserzeichen zu mehreren PDFs hinzufügen und dabei sicherstellen, dass jeweils nur ein Vorgang stattfindet.

using IronPdf;
using System;
using System.Threading;
using System.Threading.Tasks;
class program
{
    private static SemaphoreSlim _semaphore = new SemaphoreSlim(1);
    static async Task Main(string[] args)
    {
    // Setting array of tasks
        var tasks = new Task[3];
        for (int i = 0; i < tasks.Length; i++)
        {
            string inputPath = $"input_{i}.pdf";  // Input PDF file path
            string outputPath = $"output_{i}.pdf";  // Output PDF file path
            string watermarkText = @"
<img src='https://ironsoftware.com/img/products/ironpdf-logo-text-dotnet.svg'>
<h1>Iron Software</h1>";
            // Start multiple tasks to add watermarks concurrently.
            tasks[i] = AddWatermarkAsync(inputPath, outputPath, watermarkText, i);
        }
        await Task.WhenAll(tasks); // Wait for all tasks to finish.
    }
    static async Task AddWatermarkAsync(string input, string outputPath, string watermark, int taskId)
    {
        Console.WriteLine($"{DateTime.Now:HH:mm:ss} - Task {taskId} is waiting to add a watermark...");
        // Wait to enter the semaphore.
        await _semaphore.WaitAsync();
        try
        {
            Console.WriteLine($"{DateTime.Now:HH:mm:ss} - Task {taskId} is adding a watermark.");
            var pdf = PdfDocument.FromFile(input);
            pdf.ApplyWatermark(watermark); // Add watermark
            pdf.SaveAs(outputPath); // Save the modified PDF
            Console.WriteLine($"{DateTime.Now:HH:mm:ss} - Task {taskId} has completed watermarking.");
        }
        finally
        {
            // Release the semaphore after the task is done.
            _semaphore.Release();
            Console.WriteLine($"{DateTime.Now:HH:mm:ss} - Task {taskId} has released semaphore.");
        }
    }
}
using IronPdf;
using System;
using System.Threading;
using System.Threading.Tasks;
class program
{
    private static SemaphoreSlim _semaphore = new SemaphoreSlim(1);
    static async Task Main(string[] args)
    {
    // Setting array of tasks
        var tasks = new Task[3];
        for (int i = 0; i < tasks.Length; i++)
        {
            string inputPath = $"input_{i}.pdf";  // Input PDF file path
            string outputPath = $"output_{i}.pdf";  // Output PDF file path
            string watermarkText = @"
<img src='https://ironsoftware.com/img/products/ironpdf-logo-text-dotnet.svg'>
<h1>Iron Software</h1>";
            // Start multiple tasks to add watermarks concurrently.
            tasks[i] = AddWatermarkAsync(inputPath, outputPath, watermarkText, i);
        }
        await Task.WhenAll(tasks); // Wait for all tasks to finish.
    }
    static async Task AddWatermarkAsync(string input, string outputPath, string watermark, int taskId)
    {
        Console.WriteLine($"{DateTime.Now:HH:mm:ss} - Task {taskId} is waiting to add a watermark...");
        // Wait to enter the semaphore.
        await _semaphore.WaitAsync();
        try
        {
            Console.WriteLine($"{DateTime.Now:HH:mm:ss} - Task {taskId} is adding a watermark.");
            var pdf = PdfDocument.FromFile(input);
            pdf.ApplyWatermark(watermark); // Add watermark
            pdf.SaveAs(outputPath); // Save the modified PDF
            Console.WriteLine($"{DateTime.Now:HH:mm:ss} - Task {taskId} has completed watermarking.");
        }
        finally
        {
            // Release the semaphore after the task is done.
            _semaphore.Release();
            Console.WriteLine($"{DateTime.Now:HH:mm:ss} - Task {taskId} has released semaphore.");
        }
    }
}
Imports IronPdf
Imports System
Imports System.Threading
Imports System.Threading.Tasks
Friend Class program
	Private Shared _semaphore As New SemaphoreSlim(1)
	Shared Async Function Main(ByVal args() As String) As Task
	' Setting array of tasks
		Dim tasks = New Task(2){}
		For i As Integer = 0 To tasks.Length - 1
			Dim inputPath As String = $"input_{i}.pdf" ' Input PDF file path
			Dim outputPath As String = $"output_{i}.pdf" ' Output PDF file path
			Dim watermarkText As String = "
<img src='https://ironsoftware.com/img/products/ironpdf-logo-text-dotnet.svg'>
<h1>Iron Software</h1>"
			' Start multiple tasks to add watermarks concurrently.
			tasks(i) = AddWatermarkAsync(inputPath, outputPath, watermarkText, i)
		Next i
		Await Task.WhenAll(tasks) ' Wait for all tasks to finish.
	End Function
	Private Shared Async Function AddWatermarkAsync(ByVal input As String, ByVal outputPath As String, ByVal watermark As String, ByVal taskId As Integer) As Task
		Console.WriteLine($"{DateTime.Now:HH:mm:ss} - Task {taskId} is waiting to add a watermark...")
		' Wait to enter the semaphore.
		Await _semaphore.WaitAsync()
		Try
			Console.WriteLine($"{DateTime.Now:HH:mm:ss} - Task {taskId} is adding a watermark.")
			Dim pdf = PdfDocument.FromFile(input)
			pdf.ApplyWatermark(watermark) ' Add watermark
			pdf.SaveAs(outputPath) ' Save the modified PDF
			Console.WriteLine($"{DateTime.Now:HH:mm:ss} - Task {taskId} has completed watermarking.")
		Finally
			' Release the semaphore after the task is done.
			_semaphore.Release()
			Console.WriteLine($"{DateTime.Now:HH:mm:ss} - Task {taskId} has released semaphore.")
		End Try
	End Function
End Class
VB   C#

Durch Festlegen der Semaphorenzahl auf 1 mit `**private static SemaphoreSlim _semaphore = new SemaphoreSlim(1)\Wir stellen sicher, dass immer nur eine Aufgabe gleichzeitig PDFs bearbeiten kann.

Konsolenausgabe

C# Semaphoreslim(Wie es für Entwickler funktioniert): Abbildung 5

Performance-Optimierung mit SemaphoreSlim und IronPDF

Verwaltung ressourcenintensiver Vorgänge

IronPDF zeichnet sich durch die Bewältigung ressourcenintensiver Aufgaben aus, wie z. B. die Konvertierung großer HTML-Dateien in PDF-Dateien, und ist hervorragend in der Lage, diese Aufgaben in einer asynchronen Umgebung auszuführen. Die Verwendung von SemaphoreSlim zur Verwaltung dieser Vorgänge stellt sicher, dass Ihre Anwendung auch bei hoher Last ohne Leistungseinbußen reaktionsfähig bleibt.

Der folgende Beispielcode zeigt ein Szenario, in dem wir die Anzahl der gleichzeitigen großen HTML-zu-PDF-Konvertierungen begrenzen müssen, um eine Überlastung der Systemressourcen zu vermeiden.

using IronPdf;
using System;
using System.Threading;
using System.Threading.Tasks;
using IronPdf.Exceptions;
using System.Net.Http;
using System.Runtime.CompilerServices;
class program
{
    // Limit concurrent large PDF conversions to 2.
    private static SemaphoreSlim _semaphore = new SemaphoreSlim(2);
    static async Task Main(string[] args)
    {
        var tasks = new Task[4];
        for (int i = 0; i < tasks.Length; i++)
        {
            string htmlContent = $"<h1>Large Document {i}</h1><p>Content for a large HTML file {i}.</p>";
            string outputPath = $"large_output_{i}.pdf";
            // Start multiple tasks to convert large HTML files to PDFs.
            tasks[i] = ConvertLargeHtmlAsync(htmlContent, outputPath, i);
        }
        await Task.WhenAll(tasks); // Wait for all tasks to finish.
    }
    // Method to convert large HTML to PDF using SemaphoreSlim to control resource usage.
    public static async Task ConvertLargeHtmlAsync(string htmlContent, string outputPath, int taskId)
    {
        Console.WriteLine($"Task {taskId} is waiting to start conversion...");
        // Wait to enter the semaphore.
        await _semaphore.WaitAsync();
        try
        {
            Console.WriteLine($"Task {taskId} is converting large HTML to PDF.");
            var renderer = new ChromePdfRenderer();
            var pdf = await renderer.RenderHtmlAsPdfAsync(htmlContent); // Convert large HTML to PDF
            pdf.SaveAs(outputPath); // Save the PDF file
            Console.WriteLine($"Task {taskId} has completed conversion.");
        }
        finally
        {
            // Ensure the semaphore is released to allow other tasks to proceed.
            _semaphore.Release();
            Console.WriteLine($"Task {taskId} has released semaphore.");
        }
    }
}
using IronPdf;
using System;
using System.Threading;
using System.Threading.Tasks;
using IronPdf.Exceptions;
using System.Net.Http;
using System.Runtime.CompilerServices;
class program
{
    // Limit concurrent large PDF conversions to 2.
    private static SemaphoreSlim _semaphore = new SemaphoreSlim(2);
    static async Task Main(string[] args)
    {
        var tasks = new Task[4];
        for (int i = 0; i < tasks.Length; i++)
        {
            string htmlContent = $"<h1>Large Document {i}</h1><p>Content for a large HTML file {i}.</p>";
            string outputPath = $"large_output_{i}.pdf";
            // Start multiple tasks to convert large HTML files to PDFs.
            tasks[i] = ConvertLargeHtmlAsync(htmlContent, outputPath, i);
        }
        await Task.WhenAll(tasks); // Wait for all tasks to finish.
    }
    // Method to convert large HTML to PDF using SemaphoreSlim to control resource usage.
    public static async Task ConvertLargeHtmlAsync(string htmlContent, string outputPath, int taskId)
    {
        Console.WriteLine($"Task {taskId} is waiting to start conversion...");
        // Wait to enter the semaphore.
        await _semaphore.WaitAsync();
        try
        {
            Console.WriteLine($"Task {taskId} is converting large HTML to PDF.");
            var renderer = new ChromePdfRenderer();
            var pdf = await renderer.RenderHtmlAsPdfAsync(htmlContent); // Convert large HTML to PDF
            pdf.SaveAs(outputPath); // Save the PDF file
            Console.WriteLine($"Task {taskId} has completed conversion.");
        }
        finally
        {
            // Ensure the semaphore is released to allow other tasks to proceed.
            _semaphore.Release();
            Console.WriteLine($"Task {taskId} has released semaphore.");
        }
    }
}
Imports IronPdf
Imports System
Imports System.Threading
Imports System.Threading.Tasks
Imports IronPdf.Exceptions
Imports System.Net.Http
Imports System.Runtime.CompilerServices
Friend Class program
	' Limit concurrent large PDF conversions to 2.
	Private Shared _semaphore As New SemaphoreSlim(2)
	Shared Async Function Main(ByVal args() As String) As Task
		Dim tasks = New Task(3){}
		For i As Integer = 0 To tasks.Length - 1
			Dim htmlContent As String = $"<h1>Large Document {i}</h1><p>Content for a large HTML file {i}.</p>"
			Dim outputPath As String = $"large_output_{i}.pdf"
			' Start multiple tasks to convert large HTML files to PDFs.
			tasks(i) = ConvertLargeHtmlAsync(htmlContent, outputPath, i)
		Next i
		Await Task.WhenAll(tasks) ' Wait for all tasks to finish.
	End Function
	' Method to convert large HTML to PDF using SemaphoreSlim to control resource usage.
	Public Shared Async Function ConvertLargeHtmlAsync(ByVal htmlContent As String, ByVal outputPath As String, ByVal taskId As Integer) As Task
		Console.WriteLine($"Task {taskId} is waiting to start conversion...")
		' Wait to enter the semaphore.
		Await _semaphore.WaitAsync()
		Try
			Console.WriteLine($"Task {taskId} is converting large HTML to PDF.")
			Dim renderer = New ChromePdfRenderer()
			Dim pdf = Await renderer.RenderHtmlAsPdfAsync(htmlContent) ' Convert large HTML to PDF
			pdf.SaveAs(outputPath) ' Save the PDF file
			Console.WriteLine($"Task {taskId} has completed conversion.")
		Finally
			' Ensure the semaphore is released to allow other tasks to proceed.
			_semaphore.Release()
			Console.WriteLine($"Task {taskId} has released semaphore.")
		End Try
	End Function
End Class
VB   C#

Bei ressourcenintensiven Aufgaben wie der Konvertierung großer HTML-Dateien in PDFs kann SemaphoreSlim helfen, die Last auszugleichen und die Ressourcennutzung zu optimieren. Durch die Begrenzung auf 2 gleichzeitige Operationen verhindern wir, dass das System durch ressourcenintensive PDF-Generierungsaufgaben überlastet wird. Dieser Ansatz trägt dazu bei, die Arbeitslast gleichmäßiger zu verteilen und die Gesamtleistung und Stabilität der Anwendung zu verbessern.

Ausgabebild: Mit dieser Methode erzeugte Dateien

C# Semaphoreslim(Wie es für Entwickler funktioniert): Abbildung 6

Vermeiden von Deadlocks im Gleichzeitigkeitsmanagement

Deadlocks können auftreten, wenn Semaphoren nicht korrekt freigegeben werden. Eine gute Praxis, die Sie im Auge behalten sollten, ist die Verwendung von try-finally-Blöcken, um sicherzustellen, dass Semaphore auch dann freigegeben werden, wenn eine Ausnahme auftritt, um Deadlocks zu vermeiden und einen reibungslosen Ablauf Ihrer Anwendung zu gewährleisten. Einige bewährte Praktiken zur Vermeidung von Deadlocks sind die Freigabe der Semaphore im Finally-Block und die Vermeidung von blockierenden Aufrufen wie `.wait()\und "Ergebnis" in Ihrem asynchronen Code.

using IronPdf;
using System;
using System.Threading;
using System.Threading.Tasks;
using IronPdf.Exceptions;
using System.Net.Http;
using System.Runtime.CompilerServices;
class program
{
    private static SemaphoreSlim _semaphore = new SemaphoreSlim(3);
    static async Task Main(string[] args)
    {
        var tasks = new Task[3];
        for (int i = 0; i < tasks.Length; i++)
        {
            string content = $"<h1>Document {i}</h1><p>Content for PDF {i}.</p>";
            string path = $"safe_output_{i}.pdf";
            // Start multiple tasks to demonstrate deadlock-free semaphore usage.
            tasks[i] = SafePdfTaskAsync(content, path, i);
        }
        await Task.WhenAll(tasks); // Wait for all tasks to finish.
    }
    // Method demonstrating best practices for using SemaphoreSlim to avoid deadlocks.
    public static async Task SafePdfTaskAsync(string content, string path, int taskId)
    {
        Console.WriteLine($"Task {taskId} is waiting to generate PDF...");
        // Wait to enter the semaphore.
        await _semaphore.WaitAsync();
        try
        {
            Console.WriteLine($"Task {taskId} is generating PDF.");
            var renderer = new ChromePdfRenderer();
            var pdf = await renderer.RenderHtmlAsPdfAsync(content); // Render HTML to PDF
            pdf.SaveAs(path); // Save the PDF
            Console.WriteLine($"Task {taskId} has completed PDF generation.");
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Task {taskId} encountered an error: {ex.Message}");
        }
        finally
        {
            // Always release the semaphore, even if an error occurs.
            _semaphore.Release();
            Console.WriteLine($"Task {taskId} has released semaphore.");
        }
    }
}
using IronPdf;
using System;
using System.Threading;
using System.Threading.Tasks;
using IronPdf.Exceptions;
using System.Net.Http;
using System.Runtime.CompilerServices;
class program
{
    private static SemaphoreSlim _semaphore = new SemaphoreSlim(3);
    static async Task Main(string[] args)
    {
        var tasks = new Task[3];
        for (int i = 0; i < tasks.Length; i++)
        {
            string content = $"<h1>Document {i}</h1><p>Content for PDF {i}.</p>";
            string path = $"safe_output_{i}.pdf";
            // Start multiple tasks to demonstrate deadlock-free semaphore usage.
            tasks[i] = SafePdfTaskAsync(content, path, i);
        }
        await Task.WhenAll(tasks); // Wait for all tasks to finish.
    }
    // Method demonstrating best practices for using SemaphoreSlim to avoid deadlocks.
    public static async Task SafePdfTaskAsync(string content, string path, int taskId)
    {
        Console.WriteLine($"Task {taskId} is waiting to generate PDF...");
        // Wait to enter the semaphore.
        await _semaphore.WaitAsync();
        try
        {
            Console.WriteLine($"Task {taskId} is generating PDF.");
            var renderer = new ChromePdfRenderer();
            var pdf = await renderer.RenderHtmlAsPdfAsync(content); // Render HTML to PDF
            pdf.SaveAs(path); // Save the PDF
            Console.WriteLine($"Task {taskId} has completed PDF generation.");
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Task {taskId} encountered an error: {ex.Message}");
        }
        finally
        {
            // Always release the semaphore, even if an error occurs.
            _semaphore.Release();
            Console.WriteLine($"Task {taskId} has released semaphore.");
        }
    }
}
Imports IronPdf
Imports System
Imports System.Threading
Imports System.Threading.Tasks
Imports IronPdf.Exceptions
Imports System.Net.Http
Imports System.Runtime.CompilerServices
Friend Class program
	Private Shared _semaphore As New SemaphoreSlim(3)
	Shared Async Function Main(ByVal args() As String) As Task
		Dim tasks = New Task(2){}
		For i As Integer = 0 To tasks.Length - 1
			Dim content As String = $"<h1>Document {i}</h1><p>Content for PDF {i}.</p>"
			Dim path As String = $"safe_output_{i}.pdf"
			' Start multiple tasks to demonstrate deadlock-free semaphore usage.
			tasks(i) = SafePdfTaskAsync(content, path, i)
		Next i
		Await Task.WhenAll(tasks) ' Wait for all tasks to finish.
	End Function
	' Method demonstrating best practices for using SemaphoreSlim to avoid deadlocks.
	Public Shared Async Function SafePdfTaskAsync(ByVal content As String, ByVal path As String, ByVal taskId As Integer) As Task
		Console.WriteLine($"Task {taskId} is waiting to generate PDF...")
		' Wait to enter the semaphore.
		Await _semaphore.WaitAsync()
		Try
			Console.WriteLine($"Task {taskId} is generating PDF.")
			Dim renderer = New ChromePdfRenderer()
			Dim pdf = Await renderer.RenderHtmlAsPdfAsync(content) ' Render HTML to PDF
			pdf.SaveAs(path) ' Save the PDF
			Console.WriteLine($"Task {taskId} has completed PDF generation.")
		Catch ex As Exception
			Console.WriteLine($"Task {taskId} encountered an error: {ex.Message}")
		Finally
			' Always release the semaphore, even if an error occurs.
			_semaphore.Release()
			Console.WriteLine($"Task {taskId} has released semaphore.")
		End Try
	End Function
End Class
VB   C#

Durch die Verwendung eines `try-catch-finally`-Blocks haben wir sichergestellt, dass das SemaphoreSlim-Objekt immer freigegeben wird, selbst wenn eine Ausnahme ausgelöst wird, wodurch Deadlocks verhindert werden. Durch die Protokollierung von Fehlern und die ordnungsgemäße Verwaltung von Semaphore-Freigaben können wir das Programm stabil halten und unerwartetes Verhalten verhindern.

Wie Sie im Ausgabebild unten sehen können, habe ich einen Fehler simuliert, indem ich versucht habe, das Programm dazu zu bringen, eine HTML-Datei zu laden, die nicht existiert, aber selbst bei diesem Fehler gibt das Programm die Fehlermeldung aus, die mir sagt, was schief gelaufen ist, und gibt dann den Semaphor mit dem finally-Block frei.

C# Semaphoreslim(Wie es für Entwickler funktioniert): Abbildung 7

Vorteile der Verwendung von IronPDF für die gleichzeitige PDF-Verarbeitung

Effiziente und verlässliche PDF-Verarbeitung

IronPDF wurde entwickelt, um gleichzeitige PDF-Verarbeitungsaufgaben effizient zu bewältigen und bietet eine Leistung und Zuverlässigkeit, die vielen anderen PDF-Bibliotheken überlegen ist. Dank seiner robusten Architektur kann es mit den Anforderungen Ihrer Anwendung skaliert werden und ist somit ideal für Umgebungen mit hoher Nachfrage. Im Vergleich zu anderen PDF-Bibliotheken, die auf Kriterien wie Leistung, Benutzerfreundlichkeit und Robustheit basieren, erweist sich IronPDF als starker Konkurrent. Um dies zu veranschaulichen, habe ich IronPDF mit mehreren anderen beliebten PDF-Bibliotheken wie iTextSharp, PDFsharp, DinkToPdf und EvoPDF verglichen:

1. Leistung

IronPDF:

  • Rendering-Geschwindigkeit: IronPDF ist bekannt für seine schnellen und effizienten Rendering-Fähigkeiten, insbesondere bei der Konvertierung von HTML in PDF. Sie verwendet Chrome-basiertes Rendering, das eine hohe Wiedergabetreue des ursprünglichen HTML-Inhalts, einschließlich der Ausführung von CSS und JavaScript, gewährleistet.
  • Ressourcenmanagement: IronPDF ist für die Verarbeitung großer und komplexer PDF-Dateien optimiert und benötigt im Vergleich zu anderen Bibliotheken weniger Speicherplatz, wodurch es sich für Anwendungen mit hohem Volumen eignet.
  • Asynchrone Operationen: Unterstützt die asynchrone PDF-Erzeugung und ermöglicht so eine bessere Leistung in Webanwendungen, bei denen die Reaktionsfähigkeit entscheidend ist.

    iTextSharp:

  • Rendering-Geschwindigkeit: iTextSharp bietet eine gute Leistung für textlastige PDFs, kann aber bei komplexen Layouts oder Bildern deutlich langsamer werden.
  • Ressourcenmanagement: Die Speichernutzung kann mit iTextSharp höher sein, insbesondere bei der Bearbeitung großer Dokumente oder komplexer Manipulationen, was in manchen Fällen zu Leistungsengpässen führt.

    PDFsharp:

  • Rendering-Geschwindigkeit: PDFsharp ist im Allgemeinen langsamer als IronPDF, wenn es um komplexe Layouts oder die Konvertierung von HTML geht, da es keine native HTML-Rendering-Engine hat.
  • Ressourcenmanagement: Es ist weniger für die Speichernutzung optimiert und kann mit großen Dateien oder Dokumenten, die zahlreiche Bilder enthalten, Probleme haben.

    DinkToPdf:

  • Rendering-Geschwindigkeit: DinkToPdf verwendet die wkhtmltopdf-Engine, die für einfache HTML-zu-PDF-Konvertierungen gut geeignet ist, aber bei komplexeren oder dynamischen Inhalten Probleme bereiten kann.
  • Ressourcenverwaltung: Sie erfordert oft einen hohen Speicher- und Verarbeitungsaufwand und bietet keine native Unterstützung für asynchrone Operationen, was ihre Leistung in Szenarien mit hoher Last einschränkt.

    EvoPDF:

  • Rendering-Geschwindigkeit: Wie IronPDF bietet auch EvoPDF ein Chrome-basiertes Rendering und damit eine gute Leistung, insbesondere bei der Konvertierung von HTML in PDF.
  • Ressourcenmanagement: Es ist gut optimiert, kann aber aufgrund weniger aggressiver Optimierungen in einigen Szenarien mehr Ressourcen verbrauchen als IronPDF.

2. Benutzerfreundlichkeit

IronPDF:

  • API-Design: IronPDF bietet eine moderne, intuitive API, die für Entwickler aller Qualifikationsstufen einfach zu bedienen ist. Die Bibliothek ist so konzipiert, dass sie nahtlos mit .NET-Anwendungen zusammenarbeitet, was sie zu einer guten Wahl für C#-Entwickler macht.
  • Dokumentation und Support: Eine umfassende Dokumentation, eine große Anzahl von Codebeispielen und ein hervorragender Kundensupport erleichtern den Einstieg und ermöglichen eine schnelle Problemlösung.
  • Installation und Integration: Die Software kann einfach über NuGet installiert werden und lässt sich problemlos in bestehende .NET-Projekte integrieren, wobei nur eine minimale Konfiguration erforderlich ist.

    iTextSharp:

  • API Design: iTextSharp hat eine steile Lernkurve, mit einer komplexeren API, die für Anfänger überwältigend sein kann. Die Flexibilität geht auf Kosten der Einfachheit.
  • Dokumentation und Support: Obwohl gut dokumentiert, kann es aufgrund der umfangreichen Konfigurationsoptionen schwieriger werden, einfache Beispiele für gängige Aufgaben zu finden.
  • Installation und Integration: Die Software ist über NuGet verfügbar, erfordert aber ein tieferes Verständnis der API, um sie effektiv zu integrieren.

    PDFsharp:

  • API-Design: PDFsharp ist so konzipiert, dass es für grundlegende PDF-Aufgaben einfach zu handhaben ist, aber nicht sofort über fortgeschrittene Funktionen verfügt, was seine Verwendung für komplexere Szenarien einschränken kann.
  • Dokumentation und Support: Es ist eine grundlegende Dokumentation verfügbar, die jedoch im Vergleich zu IronPDF weniger umfangreich ist und keine detaillierten Beispiele für die fortgeschrittene Nutzung enthält.
  • Installation und Integration: Einfache Installation über NuGet, bietet jedoch nur begrenzte HTML-zu-PDF-Funktionen.

    DinkToPdf:

  • API-Design: Die API von DinkToPdf ist relativ einfach, aber im Vergleich zu IronPDF weniger ausgefeilt. Sie zielt hauptsächlich auf die Konvertierung von HTML in PDF ab und bietet weniger Funktionen für die direkte PDF-Bearbeitung.
  • Dokumentation und Support: Die Dokumentation ist begrenzt, und der Community-Support ist nicht so solide wie bei anderen Bibliotheken, was die Fehlerbehebung erschwert.
  • Installation und Integration: Die Installation kann komplexer sein, da zusätzliche Abhängigkeiten wie wkhtmltopdf erforderlich sind, was die Einrichtung erschweren kann.

    EvoPDF:

  • API-Design: EvoPDF bietet eine unkomplizierte API, die IronPDF ähnelt und sich stark auf die Konvertierung von HTML in PDF konzentriert, wobei die Benutzerfreundlichkeit im Vordergrund steht.
  • Dokumentation und Support: Gut dokumentiert mit guten Support-Optionen, aber nicht so umfangreich an Community-getriebenen Beispielen wie IronPDF.
  • Installation und Integration: Einfache Integration in .NET-Projekte mit verfügbaren NuGet-Paketen.

3. Robustheit

IronPDF:

  • Funktionsumfang: IronPDF ist äußerst robust und unterstützt eine breite Palette von Funktionen, darunter die Konvertierung von HTML in PDF, die Bearbeitung von PDF-Dateien, die Textextraktion, die Verschlüsselung, Anmerkungen und digitale Signaturen.
  • Fehlerbehandlung: Bietet eine robuste Fehlerbehandlung und Ausnahmeverwaltung, die es für Produktionsumgebungen zuverlässig macht.
  • Kompatibilität: Vollständig kompatibel mit .NET Core, .NET 5+ und älteren Versionen von .NET Framework, wodurch es vielseitig für verschiedene Projekttypen einsetzbar ist.

    iTextSharp:

  • Funktionsumfang: iTextSharp ist extrem robust und verfügt über einen umfassenden Funktionsumfang, der nahezu jede PDF-Aufgabe unterstützt, einschließlich komplexer Manipulationen und Formularverarbeitung.
  • Fehlerbehandlung: Gute Fehlerbehandlung, aber aufgrund der Komplexität der Bibliothek kann die Verwaltung komplex sein.
  • Kompatibilität: Gut geeignet für eine Vielzahl von Umgebungen, einschließlich .NET Framework und .NET Core.

    PDFsharp:

  • Feature Set: Grundlegende Funktionen zur Erstellung und Bearbeitung von PDF-Dateien. Es fehlen einige fortgeschrittene Funktionen wie die Konvertierung von HTML in PDF und die anspruchsvollere Bearbeitung von Dokumenten.
  • Fehlerbehandlung: Grundlegende Fehlerbehandlung; ist im Vergleich zu robusteren Bibliotheken wie IronPDF in komplexen Szenarien weniger zuverlässig.
  • Kompatibilität: Kompatibel mit .NET Framework und .NET Core, jedoch mit eingeschränkter erweiterter Funktionalität.

    DinkToPdf:

  • Funktionsumfang: Der Schwerpunkt liegt auf HTML zu PDF. Begrenzt in Bezug auf die direkte PDF-Bearbeitung und ohne erweiterte Funktionen wie Anmerkungen und Formularverarbeitung.
  • Fehlerbehandlung: Grundlegende Fehlerbehandlung; anfällig für Abstürze oder Hänger bei komplexem HTML oder großen Dateien.
  • Kompatibilität: Funktioniert mit .NET Core und .NET Framework, erfordert jedoch externe Abhängigkeiten, was zu Kompatibilitätsproblemen führen kann.

    EvoPDF:

  • Funktionsumfang: Bietet eine Reihe von Funktionen, die denen von IronPDF ähneln, einschließlich fortgeschrittener Konvertierungen von HTML in PDF und einiger Funktionen zur Dokumentenbearbeitung.
  • Fehlerbehandlung: Robuste Fehlerbehandlung und zuverlässige Leistung in Produktionsumgebungen.
  • Kompatibilität: Vollständig kompatibel mit .NET Core, .NET Framework und neueren .NET-Versionen, was es vielseitig und zuverlässig macht.

Zusammenfassung

  • Leistung: IronPDF und EvoPDF sind aufgrund ihrer Chrome-basierten Rendering-Engines führend in der Leistung, während iTextSharp und PDFsharp bei der Verarbeitung komplexer Dokumente zurückbleiben können.
  • Benutzerfreundlichkeit: IronPDF zeichnet sich durch eine intuitive API und eine umfangreiche Dokumentation aus, die es für Entwickler aller Ebenen zugänglich macht. iTextSharp bietet Leistung auf Kosten der Einfachheit, während DinkToPdf und PDFsharp einfacher, aber weniger funktionsreich sind.
  • Robustheit: IronPDF und iTextSharp bieten die robustesten Funktionssätze, wobei IronPDF eine einfachere Integration und moderne Funktionen wie Async-Unterstützung bietet, während iTextSharp mehr Nischenanwendungen mit einer steileren Lernkurve abdeckt.

Umfassende Unterstützung für asynchrone Programmierung

IronPDF lässt sich nahtlos integrieren inasynchron programmiermodelle, die Gleichzeitigkeitskontrollmechanismen wie SemaphoreSlim ergänzen. Dies ermöglicht es Entwicklern, mit minimalem Aufwand reaktionsschnelle und leistungsfähige Anwendungen zu erstellen.

IronPDF bietet außerdem umfangreiche Dokumentations- und Support-Ressourcen, die Entwicklern dabei helfen, effektive Fehlerbehandlungsverfahren zu verstehen und zu implementieren. Diese umfassende Unterstützung ist wertvoll für die Fehlersuche und Optimierung von PDF-Vorgängen in .NET-Projekten.

IronPDF bietet:

  • Umfassende Dokumentation: Ausführliche und benutzerfreundliche Dokumentation, die alle Funktionen abdeckt.
  • 24/5 Support: Aktiver Ingenieursupport ist verfügbar.
  • Video Tutorials: Schritt-für-Schritt-Videoanleitungen sind auf YouTube verfügbar.
  • Community Forum: Engagierte Community für zusätzliche Unterstützung.
  • PDF-API-Referenz: Bietet API-Referenzen, damit Sie das Beste aus unseren Tools herausholen können.

    Weitere Informationen finden Sie in IronPDFs umfangreicherDokumentation.

Schlussfolgerung

Die Verwendung von SemaphoreSlim für die Verwaltung der Gleichzeitigkeit in .NET-Anwendungen ist von entscheidender Bedeutung, insbesondere wenn es um ressourcenintensive Aufgaben wie die PDF-Verarbeitung geht. Durch die Integration von SemaphoreSlim in IronPDF können Entwickler eine sichere, effiziente und zuverlässige Gleichzeitigkeitskontrolle erreichen und sicherstellen, dass ihre Anwendungen reaktionsschnell und leistungsfreundlich bleiben.

Entdecken Sie, wie IronPDF Ihre Arbeitsabläufe bei der PDF-Verarbeitung rationalisieren kann. Probieren Sie es selbst aus mit seinerkostenloser Testbeginnt schon ab nur $749, wenn Sie dieses leistungsstarke Werkzeug in Ihren Projekten weiter nutzen möchten.

C# Semaphoreslim(Wie es für Entwickler funktioniert): Abbildung 8

< PREVIOUS
C# Init Keyword (Wie es für Entwickler funktioniert)
NÄCHSTES >
C# try catch finally (Wie es für Entwickler funktioniert)

Sind Sie bereit, loszulegen? Version: 2024.12 gerade veröffentlicht

Gratis NuGet-Download Downloads insgesamt: 11,810,873 Lizenzen anzeigen >