AIDE .NET

C# Semaphoreslim (Comment ça marche pour les développeurs)

Publié octobre 23, 2024
Partager:

Introduction

La gestion de la concurence est un aspect essentiel des applications performantes en C#. Il permet de s'assurer que les ressources sont utilisées efficacement tout en évitant les conflits potentiels ou les goulots d'étranglement au niveau des performances, c'est pourquoi il peut être très utile de disposer d'un sémaphore léger qui contrôle l'accès. C'est ici queSemaphoreSlim entre en jeu. SemaphoreSlim est une primitive de synchronisation légère qui contrôle l'accès aux ressources, ce qui permet d'éviter les conditions de course et d'assurer la sécurité des threads.

Que se passerait-il si vous vouliez mettre cela en œuvre avec une bibliothèque PDF pour gérer les processus de génération de PDF ? Vous êtes peut-être à la recherche d'une puissante bibliothèque PDF, oùIronPDF arrive. IronPDF est une bibliothèque robuste de génération et de manipulation de PDF pour les développeurs .NET qui peut grandement bénéficier de la gestion des concurrences lorsqu'elle est utilisée dans des environnements multithreads.

Si vous souhaitez voir SemaphoreSlim et IronPDF en action, ne manquez pas de lire la suite pour découvrir les avantages de l'utilisation de SemaphoreSlim et comment l'intégrer à IronPDF pour gérer en toute sécurité les opérations simultanées, améliorer les performances et garantir un traitement fiable des PDF.

Comprendre SemaphoreSlim dans C# ;

Qu'est-ce que SemaphoreSlim ?

SemaphoreSlim est une primitive de synchronisation dans .NET qui limite le nombre de threads pouvant accéder simultanément à une ressource particulière ou à un pool de ressources. Il s'agit d'une version allégée de la classe Sémaphore complète, conçue pour fonctionner plus efficacement dans les situations où un sémaphore plus simple et plus rapide est suffisant.

Les avantages de l'utilisation de SemaphoreSlim sont les suivants : la surcharge du système est réduite par rapport à Semaphore, SemaphoreSlim est idéal pour gérer des ressources limitées(comme les connexions aux bases de données ou l'accès aux fichiers)la traduction doit rester professionnelle et préserver l'exactitude technique tout en expliquant les caractéristiques et les avantages de ces outils de développement.

Exemple de code d'une utilisation basique de 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#

Au cours de l'exécution d'un programme, le nombre de sémaphores peut dynamiquement atteindre zéro thread lorsque toutes les autorisations disponibles ont été acquises par les threads. Cet état indique que le nombre maximum d'accès simultanés autorisés a été atteint.

Si vous le souhaitez, vous pouvez définir le nombre initial et le nombre maximal de threads, en commençant le décompte initial des sémaphores à zéro, puis en utilisant une tâche d'initialisation distincte qui augmente le décompte des sémaphores lorsque la ressource est prête, ce qui permet au nombre de threads que vous avez choisi de poursuivre l'exécution du projet. Lorsque le nombre de sémaphores est égal à zéro, les threads attendent lorsqu'ils essaient d'entrer dans le sémaphore, c'est ce qu'on appelle le "bloc d'attente".

Vous pourriez garder une trace du décompte précédent du sémaphore afin d'ajuster le comportement du sémaphore en fonction du décompte précédent, vous pouvez alors manipuler le sémaphore en conséquence(par exemple, en libérant ou en attendant). Au fur et à mesure que les threads se libèrent, le nombre de sémaphores diminue.

Sortie de la console

C# Semaphoreslim(Comment ça marche pour les développeurs) : Figure 1

Cas d'utilisation courants pour SemaphoreSlim

Voici quelques cas d'utilisation courants de SemaphoreSlim :

  • Limiter l'accès aux bases de données ou aux systèmes de fichiers: Cela évite de submerger ces ressources avec un trop grand nombre de requêtes simultanées.
  • **Il peut être utilisé pour contrôler le nombre de threads effectuant une opération particulière, améliorant ainsi la stabilité et les performances.

Utilisation de SemaphoreSlim avec IronPdf pour une Concurrence Sécurisée

Mise en place d'IronPDF dans un environnement multithreads

Pour commencer à utiliser IronPDF dans un environnement multithread, commencez par installer l'applicationPaquet NuGet IronPDF. Vous pouvez le faire en naviguant vers outils > NuGet Package Manager > NuGet Package Manager for Solution et en recherchant IronPDF :

C# Semaphoreslim(Comment ça marche pour les développeurs) : Figure 2

Ou encore, en exécutant la commande suivante dans la console du gestionnaire de paquets :

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

Pour commencer à utiliser IronPDF dans votre code, assurez-vous d'avoir placé la déclaration `utilisant IronPdf` en haut de votre fichier de code. Pour un guide plus approfondi de la mise en place d'IronPDF dans votre environnement, consultez son site Webpour commencer page.

Contrôler l'accès à la génération de PDF avec SemaphoreSlim

En utilisant SemaphoreSlim, vous pouvez contrôler efficacement l'accès aux tâches de génération de PDF. Cela permet de s'assurer que votre application ne tente pas de générer trop de PDF simultanément, ce qui pourrait avoir un impact sur les performances ou provoquer des défaillances.

L'exemple de code suivant démontre l'utilisation de base de SemaphoreSlim avec 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#

Dans cet exemple, nous avons d'abord initialisé SemaphoreSlim et défini le nombre initial et maximal de SemaphoreSlim à "2", ce qui le limite à deux générations simultanées de PDF. Nous avons ensuite créé un tableau de tâches qui est utilisé pour contrôler le nombre de tâches que le programme doit effectuer, après quoi nous utilisons une boucle for pour créer dynamiquement des PDF en fonction du nombre de tâches dans le tableau de tâches.

L'objet de la traduction est le suivant : "WaitAsync()la méthode \Nest alors utilisée pour entrer dans le sémaphore, et \NRelease()``** est utilisé dans le bloc finally pour s'assurer que le sémaphore est toujours libéré même si une exception se produit. Les journaux de sortie de la console indiquent quand chaque tâche commence, finit et libère le sémaphore, ce qui vous permet de suivre le comportement de la concurrence.

Console de sortie

C# Semaphoreslim(Comment ça marche pour les développeurs) : Figure 3

Fichiers PDF de sortie

C# Semaphoreslim(Comment ça marche pour les développeurs) : Figure 4

Assurer la sécurité des threads dans les tâches de manipulation des PDF

La sécurité des threads est cruciale lorsque plusieurs threads interagissent avec des ressources partagées. Dans la manipulation des PDF, SemaphoreSlim garantit que seul un nombre défini de threads peut modifier les PDF simultanément, évitant ainsi les conditions de course et garantissant la cohérence. Dans le code suivant, nous simulons un scénario dans lequel nous ajoutons un filigrane à plusieurs PDF tout en veillant à ce qu'une seule opération se produise à la fois.

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#

En fixant le nombre de sémaphores à 1 à l'aide de `private static SemaphoreSlim _semaphore = new SemaphoreSlim(1)``, nous veillons à ce qu'une seule tâche puisse manipuler les PDF à la fois.

Sortie de la console

C# Semaphoreslim(Comment ça marche pour les développeurs) : Figure 5

Optimiser les performances avec SemaphoreSlim et IronPdf

Gestion des opérations à forte intensité de ressources

IronPDF excelle dans le traitement de tâches gourmandes en ressources, telles que la conversion de fichiers HTML volumineux en PDF, et excelle dans l'exécution de ces tâches dans un environnement asynchrone. L'utilisation de SemaphoreSlim pour gérer ces opérations garantit que votre application reste réactive sans perdre en performance, même en cas de forte charge.

L'exemple de code suivant illustre un scénario dans lequel nous devons limiter le nombre de conversions simultanées de gros fichiers HTML en fichiers PDF afin d'éviter de surcharger les ressources du système.

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#

Lorsqu'il s'agit de tâches gourmandes en ressources, comme la conversion de fichiers HTML volumineux en PDF, SemaphoreSlim peut aider à équilibrer la charge et à optimiser l'utilisation des ressources. En fixant une limite de 2 opérations simultanées, nous évitons que le système ne soit submergé par des tâches de génération de PDF gourmandes en ressources. Cette approche permet de mieux répartir la charge de travail et d'améliorer les performances et la stabilité de l'application dans son ensemble.

Image de sortie : Fichiers générés avec cette méthode

C# Semaphoreslim(Comment ça marche pour les développeurs) : Figure 6

Éviter les blocages dans la gestion de la concurence

Des blocages peuvent se produire si les sémaphores ne sont pas libérés correctement. Une bonne pratique à garder à l'esprit est l'utilisation de blocs try-finally pour s'assurer que les sémaphores sont libérés même si une exception se produit, évitant ainsi les blocages et assurant le bon fonctionnement de votre application. Parmi les meilleures pratiques à retenir pour éviter les blocages, citons le fait de toujours libérer le sémaphore dans le bloc finally et d'éviter d'utiliser des appels bloquants tels que `.wait()\Net \N.Result\Nà l'intérieur de votre code asynchrone.

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#

En utilisant un bloc `try-catch-finally`, nous nous sommes assurés que l'objet SemaphoreSlim est toujours libéré, même si une exception est levée, ce qui permet d'éviter les blocages. En enregistrant les erreurs et en gérant correctement les libérations de sémaphores, nous pouvons maintenir le programme stable et éviter tout comportement inattendu.

Comme vous pouvez le voir dans l'image de sortie ci-dessous, j'ai simulé une erreur en essayant de faire en sorte que le programme charge un fichier HTML qui n'existe pas, mais même avec cette erreur, le programme imprime le message d'erreur qui m'indique ce qui n'a pas fonctionné et procède ensuite à la libération du sémaphore à l'aide du bloc finally.

C# Semaphoreslim(Comment ça marche pour les développeurs) : Figure 7

Avantages de l'utilisation d'IronPDF pour le traitement simultané des PDF

Traitement efficace et fiable des PDF

IronPDF est conçu pour gérer efficacement les tâches de traitement PDF simultanées, offrant des performances et une fiabilité supérieures à celles de nombreuses autres bibliothèques PDF. Son architecture robuste lui permet de s'adapter aux besoins de votre application, ce qui en fait un outil idéal pour les environnements à forte demande. Lorsqu'on la compare à d'autres bibliothèques PDF sur la base de critères de performance, de facilité d'utilisation et de robustesse, IronPDF s'avère être un concurrent de taille. Pour le démontrer, j'ai comparé IronPdf à plusieurs autres bibliothèques PDF populaires telles que iTextSharp, PDFsharp, DinkToPdf et EvoPDF :

1. Performance

IronPDF :

  • Vitesse de rendu: IronPDF est connu pour ses capacités de rendu rapides et efficaces, notamment lors de la conversion de HTML en PDF. Elle utilise le rendu basé sur Chrome, qui offre une grande fidélité au contenu HTML d'origine, y compris l'exécution CSS et JavaScript.
  • Gestion des ressources: IronPDF est optimisé pour traiter des PDF volumineux et complexes avec une utilisation moindre de la mémoire par rapport à d'autres bibliothèques, ce qui le rend adapté aux applications à fort volume.
  • Opérations asynchrones: Prise en charge de la génération asynchrone de PDF, permettant de meilleures performances dans les applications web où la réactivité est cruciale.

    iTextSharp:

  • Vitesse de rendu: iTextSharp offre de bonnes performances pour les PDF contenant beaucoup de texte, mais peut ralentir de manière significative avec des mises en page complexes ou des images.
  • Gestion des ressources: L'utilisation de la mémoire peut être plus importante avec iTextSharp, en particulier lors de la manipulation de documents volumineux ou de manipulations complexes, ce qui entraîne dans certains cas des goulets d'étranglement au niveau des performances.

    PDFsharp :

  • Vitesse de rendu: PDFsharp est généralement plus lent qu'IronPDF lorsqu'il s'agit de mises en page complexes ou lors de la conversion à partir de HTML, car il ne dispose pas d'un moteur de rendu HTML natif.
  • **Il est moins optimisé pour l'utilisation de la mémoire et peut avoir des difficultés avec les fichiers volumineux ou les documents contenant de nombreuses images.

    DinkToPdf :

  • Vitesse de rendu: DinkToPdf utilise le moteur wkhtmltopdf, qui est efficace pour les conversions HTML vers PDF de base mais peut s'avérer difficile avec des contenus plus complexes ou dynamiques.
  • **La traduction doit rester professionnelle et préserver l'exactitude technique tout en expliquant les caractéristiques et les avantages de ces outils de développement.

    EvoPDF:

  • Vitesse de rendu: EvoPDF fournit également un rendu basé sur Chrome comme IronPDF, offrant de bonnes performances, notamment pour les conversions HTML vers PDF.
  • Gestion des ressources: Il est bien optimisé mais pourrait encore consommer plus de ressources par rapport à IronPDF dans certains scénarios en raison d'optimisations moins agressives.

2. **Facilité d'utilisation

IronPDF :

  • Conception de l'API: IronPDF offre une API moderne et intuitive, facile à utiliser pour les développeurs de tous niveaux de compétence. La bibliothèque est conçue pour fonctionner de manière transparente avec les applications .NET, ce qui en fait un excellent choix pour les développeurs C#.
  • Documentation et assistance: Une documentation complète, un grand nombre d'exemples de code et une excellente assistance à la clientèle facilitent la prise en main et la résolution rapide des problèmes.
  • Installation et intégration: Facile à installer via NuGet et s'intègre en douceur dans les projets .NET existants, ne nécessitant qu'une configuration minimale.

    iTextSharp:

  • Conception de l'API: iTextSharp a une courbe d'apprentissage abrupte, avec une API plus complexe qui peut être accablante pour les débutants. Sa flexibilité se fait au détriment de la simplicité.
  • Documentation et assistance: Bien que bien documenté, le grand nombre d'options de configuration peut rendre plus difficile la recherche d'exemples simples pour les tâches courantes.
  • Installation et intégration: Disponible via NuGet, mais nécessite une compréhension plus approfondie de l'API pour une intégration efficace.

    PDFsharp :

  • Conception de l'API: PDFsharp est conçu pour être simple pour les tâches PDF de base mais manque de fonctionnalités avancées, ce qui peut limiter son utilisation pour des scénarios plus complexes.
  • Documentation et support: Une documentation de base est disponible, mais elle est moins complète et manque d'exemples détaillés pour une utilisation avancée par rapport à IronPDF.
  • Installation et intégration: Facile à installer via NuGet mais offre des fonctionnalités HTML vers PDF limitées.

    DinkToPdf :

  • Conception de l'API: L'API de DinkToPdf est relativement simple mais moins soignée que celle d'IronPDF. Elle vise principalement la conversion de HTML en PDF et offre moins de fonctionnalités pour la manipulation directe de PDF.
  • Documentation et support: La documentation est limitée et le support communautaire n'est pas aussi solide que pour d'autres bibliothèques, ce qui rend le dépannage plus difficile.
  • Installation et intégration: Peut être plus complexe à installer, nécessitant des dépendances supplémentaires comme wkhtmltopdf, ce qui peut compliquer l'installation.

    EvoPDF:

  • Conception de l'API: EvoPDF fournit une API directe similaire à celle d'IronPDF, fortement axée sur la conversion de HTML en PDF dans un souci de simplicité d'utilisation.
  • Documentation et support: Bien documenté avec de bonnes options de support, mais pas aussi étendu dans les exemples dirigés par la communauté qu'IronPDF.
  • Installation et intégration: Facile à intégrer dans les projets .NET grâce aux packages NuGet disponibles.

3. **Robustesse

IronPDF :

  • Feature Set: IronPDF est très robuste, prenant en charge un large éventail de fonctionnalités, notamment la conversion de HTML en PDF, l'édition de PDF, l'extraction de texte, le cryptage, les annotations et les signatures numériques.
  • Gestion des erreurs: Offre une gestion robuste des erreurs et des exceptions, ce qui le rend fiable pour les environnements de production.
  • Compatibilité: Entièrement compatible avec .NET Core, .NET 5+ et les anciennes versions de .NET Framework, ce qui le rend polyvalent à travers différents types de projets.

    iTextSharp:

  • **iTextSharp est extrêmement robuste avec un ensemble complet de fonctionnalités qui prend en charge presque toutes les tâches PDF, y compris les manipulations complexes et la gestion des formulaires.
  • Gestion des erreurs: Bonne gestion des erreurs, mais peut être complexe à gérer en raison des subtilités de la bibliothèque.
  • Compatibilité: Bien adapté à un large éventail d'environnements, notamment .NET Framework et .NET Core.

    PDFsharp :

  • Fonctionnalités: Fonctions de base de création et de manipulation de PDF. Il manque certaines fonctionnalités avancées telles que la conversion de HTML en PDF et l'édition de documents plus sophistiqués.
  • Gestion des erreurs: Gestion des erreurs de base ; est moins fiable dans des scénarios complexes par rapport à des bibliothèques plus robustes comme IronPDF.
  • Compatibilité: Compatible avec .NET Framework et .NET Core, mais avec des fonctionnalités avancées limitées.

    DinkToPdf :

  • Caractéristiques: Principalement axé sur la traduction de HTML en PDF. Limité en termes de manipulation directe des PDF et dépourvu de fonctions avancées telles que les annotations et la gestion des formulaires.
  • Gestion des erreurs: Gestion des erreurs de base ; le logiciel a tendance à se bloquer ou à se bloquer sur des fichiers HTML complexes ou des fichiers volumineux.
  • Compatibilité: Fonctionne avec .NET Core et .NET Framework mais nécessite des dépendances externes, ce qui peut introduire des problèmes de compatibilité.

    EvoPDF:

  • Feature Set: Offre un solide ensemble de fonctionnalités similaires à celles d'IronPDF, notamment des conversions HTML vers PDF avancées et certaines capacités de manipulation de documents.
  • Gestion des erreurs: Gestion robuste des erreurs et performances fiables dans les environnements de production.
  • Compatibilité: Entièrement compatible avec .NET Core, .NET Framework et les versions .NET plus récentes, ce qui le rend polyvalent et fiable.

Résumé

  • Performance: IronPDF et EvoPDF sont les plus performants grâce à leurs moteurs de rendu basés sur Chrome, tandis qu'iTextSharp et PDFsharp peuvent être à la traîne dans le traitement de documents complexes.
  • Facilité d'utilisation: IronPDF excelle grâce à son API intuitive et sa documentation complète, ce qui le rend accessible à tous les niveaux de développeurs. iTextSharp offre de la puissance au détriment de la simplicité, tandis que DinkToPdf et PDFsharp sont plus faciles à utiliser mais moins riches en fonctionnalités.
  • Robustesse: IronPDF et iTextSharp offrent les ensembles de fonctionnalités les plus robustes, IronPDF offrant une intégration plus simple et des fonctionnalités modernes telles que la prise en charge asynchrone, tandis qu'iTextSharp couvre des cas d'utilisation plus niches avec une courbe d'apprentissage plus raide.

Prise en charge complète de la programmation asynchrone

IronPDF s'intègre parfaitement àasynchrone la traduction doit rester professionnelle, en préservant l'exactitude technique tout en expliquant les caractéristiques et les avantages de ces outils de développement. Cela permet aux développeurs de créer des applications réactives et performantes avec un minimum d'efforts.

IronPDF propose également une documentation complète et des ressources d'assistance qui aident les développeurs à comprendre et à mettre en œuvre des pratiques efficaces de traitement des erreurs. Ce support complet est précieux pour dépanner et optimiser les opérations PDF dans les projets .NET.

IronPDF propose :

  • Documentation complète: Documentation étendue et conviviale couvrant toutes les fonctionnalités.
  • Support 24/5: Le support actif des ingénieurs est disponible.
  • Tutoriels Vidéo : Des guides vidéo pas à pas sont disponibles sur YouTube.
  • Forum Communautaire : Une communauté engagée pour un support supplémentaire.
  • Référence API PDF : Offre des références API pour que vous puissiez tirer le meilleur parti de ce que nos outils ont à offrir.

    Pour plus d'informations, consultez la vaste documentation d'IronPDF.la documentation.

Conclusion

L'utilisation de SemaphoreSlim pour la gestion de la concurrence dans les applications .NET est cruciale, en particulier lorsqu'il s'agit de tâches gourmandes en ressources comme le traitement des PDF. En intégrant SemaphoreSlim à IronPDF, les développeurs peuvent obtenir un contrôle des concurrences sûr, efficace et fiable, garantissant que leurs applications restent réactives et respectueuses des performances.

Découvrez comment IronPdf peut rationaliser vos flux de travail de traitement des PDF. Essayez-le par vous-même avec sonessai gratuit le prix de la traduction commence à partir de 749 $ seulement si vous souhaitez que cet outil puissant soit utilisé dans vos projets.

C# Semaphoreslim(Comment ça marche pour les développeurs) : Figure 8

< PRÉCÉDENT
C# Init Keyword (Comment ça marche pour les développeurs)
SUIVANT >
C# try catch finally (Comment ça marche pour les développeurs)