ライブ環境でテストする
ウォーターマークなしで本番環境でテストしてください。
必要な場所でいつでも動作します。
並行性管理は、C#の高性能アプリケーションの重要な側面です。 潜在的な競合やパフォーマンスのボトルネックを回避しながら、リソースを効率的に利用することを保証するため、軽量なセマフォがアクセスを制御することは非常に役立ちます。 ここはセマフォスリム登場します。 SemaphoreSlimは軽量な同期プリミティブで、リソースへのアクセスを制御し、最終的に競合状態を防いでスレッドの安全性を確保します。
では、これをPDF生成プロセスを管理するPDFライブラリと一緒に実装したいとしたらどうでしょう? 以下のような強力なPDFライブラリを探しているかもしれません。IronPDF登場します。 IronPDFは.NET開発者のための堅牢なPDF生成・操作ライブラリで、マルチスレッド環境で使用される場合、並行性管理から大きな恩恵を受けることができます。
SemaphoreSlimとIronPDFが実際に動作しているところをご覧になりたい場合は、SemaphoreSlimを使用する利点と、並行処理を安全に処理し、パフォーマンスを向上させ、信頼できるPDF処理を保証するためにIronPDFと統合する方法を探りますので、ぜひお読みください。
SemaphoreSlimは、.NETの同期プリミティブで、特定のリソースまたはリソースプールに同時にアクセスできるスレッド数を制限します。 これは完全なSemaphoreクラスの軽量版であり、よりシンプルで高速なセマフォで十分な状況で、より効率的に動作するように設計されています。
SemaphoreSlimを使用する利点は、Semaphoreに比べてシステムのオーバーヘッドが削減され、限られたリソースの管理に最適であることです。(データベース接続やファイルアクセスなど)また、非同期待機メソッドをサポートしているため、最新の非同期/待機プログラミングパターンに適しています。
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
プログラムの動作中、利用可能なパーミッションがすべてスレッドによって取得されると、セマフォのカウントは動的にゼロスレッドになることがあります。 この状態は、許可された最大同時アクセス数に達したことを示します。
必要であれば、初期スレッド数と最大スレッド数を設定し、初期セマフォ・カウントをゼロで開始し、リソースの準備ができたときにセマフォ・カウントを増加させる別の初期化タスクを使用して、選択したスレッド数で処理を進めることができます。 セマフォのカウントがゼロの場合、スレッドはセマフォに入ろうとすると待機します。
セマフォの動作を調整するために、以前のセマフォのカウントを追跡することができます。(例:リリースまたは待機によって). スレッドが解放されると、セマフォ・カウントが減少します。
SemaphoreSlimの一般的な使用例は以下のとおりです:
マルチスレッド環境でIronPDFを使い始めるには、まずIronPDF NuGetパッケージ. tools > NuGet Package Manager > NuGet Package Manager for Solutionに移動し、IronPDFを検索することで可能です:
あるいは、パッケージマネージャーコンソールで次のコマンドを実行してください:
Install-Package IronPdf
Install-Package IronPdf
'INSTANT VB TODO TASK: The following line uses invalid syntax:
'Install-Package IronPdf
あなたのコードでIronPDFを使い始めるには、あなたのコードファイルの先頭に "using IronPdf "ステートメントがあることを確認してください。あなたの環境でIronPDFをセットアップするためのより詳細なガイドについては、そのはじめにページ
SemaphoreSlimを使用すると、PDF生成タスクへのアクセスを効果的に制御できます。 これにより、アプリケーションが同時に多くのPDFを生成しようとして、パフォーマンスに影響を与えたり、障害を引き起こしたりしないようにします。
次のコード例は、SemaphoreSlimと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
この例では、まずSemaphoreSlimを初期化し、SemaphoreSlimの初期カウントと最大カウントを'2'に設定し、同時PDF生成を2回に制限しています。 次に、プログラムが行うべきタスクの数を制御するために使用されるタスク配列を作成し、その後、タスク配列内のタスクの数に基づいて動的にPDFを作成するためにforループを使用します。
The `WaitAsync()\次に、セマフォを入力するために`メソッドが使用され、Release()\例外が発生した場合でも、セマフォが常に解放されるようにするために、finally ブロックで ``***
が使用されています。 コンソール出力ログは、各タスクがいつ開始し、いつ終了し、セマフォを解放したかを示し、これにより並行動作の追跡が可能になります。
スレッドセーフは、複数のスレッドが共有リソースとやり取りする際に非常に重要です。 PDF操作において、SemaphoreSlimは定義された数のスレッドのみが同時にPDFを変更できるようにし、競合状態を防ぎ、一貫性を確保します。 以下のコードでは、一度に1つの操作しか起こらないようにしながら、複数のPDFに透かしを追加するシナリオをシミュレートしています。
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
を使用してセマフォカウントを1に設定します。(1)\また、一度に1つのタスクだけがPDFを操作できるようにします。
IronPDFは大きなHTMLファイルをPDFに変換するようなリソース集約的なタスクを処理し、非同期環境でこれらのタスクを実行することに優れています。 SemaphoreSlimを使用してこれらの操作を管理することで、高負荷時でもパフォーマンスを低下させることなくアプリケーションの応答性を維持することができます。
次のコード例は、システムリソースに過負荷をかけないように、同時に行われる大きなHTMLからPDFへの変換の数を制限する必要があるシナリオを示しています。
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
大きなHTMLファイルをPDFに変換するようなリソースを大量に必要とするタスクでは、SemaphoreSlimが負荷のバランスをとり、リソースの使用を最適化します。 同時処理の上限を2つに設定することで、リソース集約的なPDF生成タスクによってシステムが圧倒されるのを防ぎます。 このアプローチにより、作業負荷が均等に分散され、アプリケーション全体のパフォーマンスと安定性が向上します。
セマフォが正しく解放されないと、デッドロックが発生する可能性があります。 留意すべき良い習慣は、例外が発生してもセマフォが解放されるようにtry-finallyブロックを使用することです。 デッドロックを回避するために覚えておくべきベストプラクティスには、必ずfinallyブロックの中でセマフォを解放すること、 `.wait のようなブロッキングコールを使用しないことなどがあります。()\非同期コードの中に.Result`を記述してください。
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
Try-catch-finally-***ブロックを使用することで、例外がスローされてもSemaphoreSlimオブジェクトが常に解放されるようにし、デッドロックを防止しています。 エラーをログに記録し、セマフォの解放を適切に管理することで、プログラムを安定させ、予期せぬ動作を防ぐことができます。
下の出力画像でわかるように、存在しないHTMLファイルをプログラムに読み込ませようとしてエラーをシミュレートしましたが、このエラーでも、プログラムは何が間違っていたかを教えてくれるエラーメッセージを表示し、finallyブロックを使ってセマフォの解放に進みます。
IronPDFは同時PDF処理タスクを効率的に処理するように設計されており、他の多くのPDFライブラリよりも優れたパフォーマンスと信頼性を提供します。 堅牢なアーキテクチャにより、アプリケーションのニーズに合わせて拡張できるため、需要の高い環境に最適です。 パフォーマンス、使いやすさ、堅牢性を基準に他のPDFライブラリと比較すると、IronPDFは強力な競争相手であることがわかります。 これを紹介するために、私はIronPDFをiTextSharp, PDFsharp, DinkToPdf, EvoPDFのような他の人気のあるPDFライブラリと比較しました:
IronPDF:
非同期操作: 非同期 PDF 生成をサポートし、応答性が重要な Web アプリケーションでより良いパフォーマンスを可能にします。
iTextSharp:
リソース管理: iTextSharpでは、特に大きな文書や複雑な操作を行う場合にメモリ使用量が多くなり、パフォーマンスのボトルネックになる場合があります。
PDFsharp:
*リソース管理:*** メモリ使用量があまり最適化されていないため、大きなファイルや多数の画像を含む文書で苦労することがあります。
DinkToPdf:
リソース管理: 多くの場合、多大なメモリと処理能力を必要とし、非同期操作のネイティブサポートがないため、高負荷シナリオでのパフォーマンスが制限されます。
EvoPDF:
IronPDF:
インストールと統合: NuGet経由で簡単にインストールでき、既存の.NETプロジェクトにスムーズに統合できるため、最小限の設定しか必要としません。
iTextSharp:
インストールと統合: NuGetを通じて利用可能ですが、効果的に統合するにはAPIをより深く理解する必要があります。
PDFsharp:
インストールと統合: NuGet経由で簡単にインストールできますが、HTMLからPDFへの機能は限られています。
DinkToPdf:
インストールと統合: wkhtmltopdf のような追加の依存関係を必要とするため、インストールが複雑になることがあります。
EvoPDF:
IronPDF:
互換性: .NET Core、.NET 5+、およびレガシーの.NET Frameworkバージョンと完全な互換性があり、さまざまなプロジェクトタイプで汎用性があります。
iTextSharp:
**.NET Frameworkや.NET Coreを含む幅広い環境に適しています。
PDFsharp:
**.NET Frameworkおよび.NET Coreと互換性がありますが、高度な機能には制限があります。
DinkToPdf:
互換性: .NET Coreと.NET Frameworkで動作しますが、外部依存関係が必要なため、互換性の問題が発生する可能性があります。
EvoPDF:
IronPdfは以下とシームレスに統合します。非同期SemaphoreSlimのような同時実行制御メカニズムを補完するプログラミングモデル。 これにより、開発者は最小限の労力で、応答性とパフォーマンスに優れたアプリケーションを構築できるようになります。
IronPDFはまた、開発者が効果的なエラーハンドリングを理解し、実践できるよう、広範なドキュメントとサポートリソースを提供します。 この包括的なサポートは、.NETプロジェクトにおけるPDF操作のトラブルシューティングや最適化に役立ちます。
IronPdfは提供します:
PDF APIリファレンス: 弊社のツールの提供する機能を最大限に活用できるように、APIリファレンスを提供します。
詳しい情報は、IronPDFの詳細をご覧ください。ドキュメント.
.NETアプリケーションの同時実行管理にSemaphoreSlimを使用することは、特にPDF処理のようなリソースを大量に消費するタスクを処理する場合に重要です。 SemaphoreSlimとIronPDFを統合することで、開発者は安全で効率的、かつ信頼性の高い並行性制御を実現し、アプリケーションの応答性とパフォーマンスを維持することができます。
IronPDFがどのようにPDF処理のワークフローを効率化するかをご覧ください。 この翻訳を無料試用あなたのプロジェクトでこの強力なツールを使い続けたい場合は、わずか749ドルから始めることができます。
9つの .NET API製品 オフィス文書用