Test dans un environnement réel
Test en production sans filigrane.
Fonctionne partout où vous en avez besoin.
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.
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.
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
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.
Voici quelques cas d'utilisation courants de SemaphoreSlim :
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 :
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
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.
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
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.
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
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.
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
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.
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
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.
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 :
IronPDF :
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:
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 :
**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 :
**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:
IronPDF :
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:
Installation et intégration: Disponible via NuGet, mais nécessite une compréhension plus approfondie de l'API pour une intégration efficace.
PDFsharp :
Installation et intégration: Facile à installer via NuGet mais offre des fonctionnalités HTML vers PDF limitées.
DinkToPdf :
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:
IronPDF :
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:
Compatibilité: Bien adapté à un large éventail d'environnements, notamment .NET Framework et .NET Core.
PDFsharp :
Compatibilité: Compatible avec .NET Framework et .NET Core, mais avec des fonctionnalités avancées limitées.
DinkToPdf :
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:
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 :
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.
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.
9 produits de l'API .NET pour vos documents de bureau