.NET ヘルプ

C# インターロック (開発者のための仕組み)

チペゴ
チペゴ・カリンダ
2025年4月3日
共有:

マルチスレッドアプリケーションを扱う際、スレッドセーフを確保することは、競合状態やデータ破損を防ぐための重要な要素となります。 PDF 処理の世界における IronPDF でも、この問題は例外ではありません。 PDFを生成、操作、または結合する際に、適切な同期が保たれていないと、これらのタスクを同時に実行することで予期しない結果が生じる可能性があります。 これは、マルチスレッド環境でスレッドセーフな操作を確保するためのシンプルで効率的な方法を提供するC#のInterlockedクラスが活躍する場面です。

C#のInterlockedクラスとは何ですか?

C# では、Interlocked クラスが複数のスレッドによって共有される変数に対してアトミック操作を提供します。 これにより、あるスレッドの動作が別のスレッドによって妨げられることがないようにします。これは、操作が制御され、一貫して実行されることを保証する必要がある場合に不可欠です。 一方、IronPDFは.NET開発者がPDFを作成、編集、操作できる強力なライブラリです。

インターロックを使用したスレッドセーフティとIronPDFを使用したPDF操作を組み合わせることで、並行プログラミングにおけるPDFタスクを処理するための強力なソリューションを得ることができます。 しかし、これはどのように機能し、なぜ気にする必要があるのでしょうか? IronPDFの処理におけるInterlockedの役割をさらに深く掘り下げましょう。

IronPDF: オールインワンC# PDFライブラリ

C# Interlocked(開発者向けの仕組み):図1

Pixabay から追加アップロード

またはここに画像をドラッグアンドドロップします

画像の代替テキストを追加

IronPDF は、C# および .NET アプリケーションとシームレスに連携して、PDF の生成と操作を行うために設計された多機能で豊富な機能を持つライブラリです。 そのシンプルさとパフォーマンスにより、PDFタスクを自動化する必要がある開発者にとって人気の選択肢となっています。 以下はIronPDFの主な機能です:

  • HTML から PDF への変換: IronPDF は、HTML コンテンツ を高品質の PDF に変換することができます。 これは、特にレポート、請求書、およびHTMLでレンダリングされるコンテンツを作成するのに役立ちます。
  • PDF編集と操作:既存のPDF文書を結合分割、またはページ抽出によって操作できます。 さらに、IronPDFを使用すると、PDF内のコンテンツを修正することができます。例えば、テキスト画像、または注釈を追加することができます。
  • PDFフォームとフィールド:IronPDFは、PDFフォームの操作をサポートしており、フォームフィールドのプログラムによる入力が含まれます。 これは、アンケート、申請書、契約書などの文書を自動生成するプロセスに理想的です。
  • デジタル署名: これは、PDFをデジタル署名で署名するための機能を提供し、法務および金融分野など、安全な文書取引を必要とする業界にとって重要な機能です。

    これらの機能を活用することで、IronPDFは開発者がPDFワークフローを効率的に作成、管理、自動化しながら、高品質な結果を保証します。 動的なHTMLコンテンツを操作している場合でも、既存のドキュメントを操作している場合でも、IronPDFはPDF関連の作業を効率化するために必要なツールを提供します。

なぜIronPDF処理でInterlockedを使用するのか?

スレッドセーフティと並行性

マルチスレッドのアプリケーションでは、複数のスレッドが同時に共有データにアクセスして変更を試みることがあります。適切な同期がなければ、これは競合状態のような問題を引き起こす可能性があり、同時に2つのスレッドが同じデータを更新しようとします。 これは予測不可能な結果やデバッグが困難なエラーを引き起こす可能性があります。

Interlocked クラスは、これらの同時操作が原子的に処理されることを保証します。 つまり、Interlockedを使用してオブジェクトの値を変更する場合、その変更は単一の中断不可能な操作として行われるため、競合状態のリスクが排除されます。

IronPDFの文脈では、ページの追加、コンテンツの編集、複数のソースからのPDFの生成など、多くのPDF処理タスクは並列処理に理想的な候補です。 同期を取らずにこれらの操作を同時に実行すると、PDFファイルが破損したり、処理中にエラーが発生する可能性があります。 Interlockedを使用することで、これらの操作がマルチスレッド環境でも安全に保たれることが保証されます。

異なるデータ型でインターロックを使用する

異なるデータ型の変数を扱う場合、Interlocked を使用して同時更新を安全に管理することができます。 考えられるデータ型をいくつか見てみましょう:

  • 浮動小数点値: Interlocked.CompareExchange メソッドは、操作に参照型が必要な場合に浮動小数点値と共に使用できます。
  • 元の値: 更新を行う際には、スレッド操作の一貫性を確保するために変更を加える前に元の値で作業することが重要です。
  • パブリック スタティック クラス: 公開されている静的クラスを作成して、インターロック操作をカプセル化することで、コードをよりモジュラー化し、メンテナンスしやすくすることができます。
  • ダブル値: Interlocked は直接ダブル値をサポートしていません。これは、double が整数型ではなく、アトミック操作が整数に最適化されているためです。 double 値に対するアトミック操作が必要な場合、long 値を使用し、double 値と long 値の間で手動で変換することで回避できます。
public static class ThreadSafeOperations
{
    private static int counter = 0;
    public static void IncrementCounter()
    {
        // Safely increment the counter using Interlocked
        Interlocked.Increment(ref counter);
    }
}
public static class ThreadSafeOperations
{
    private static int counter = 0;
    public static void IncrementCounter()
    {
        // Safely increment the counter using Interlocked
        Interlocked.Increment(ref counter);
    }
}
Public Module ThreadSafeOperations
	Private counter As Integer = 0
	Public Sub IncrementCounter()
		' Safely increment the counter using Interlocked
		Interlocked.Increment(counter)
	End Sub
End Module
$vbLabelText   $csharpLabel

IronPDFでInterlockedを使用するタイミング

複数のスレッドが共有リソースを扱っている状況では、Interlocked を使用するべきです。 例を挙げよう:

  • PDF生成におけるページ番号の追跡。
  • 複数のスレッドによってアクセスおよび修正されるカウンターやリストの管理。

    これらの操作にインターロックを使用することで、更新がスレッドセーフとなり、競合を防ぎ、データの整合性を確保します。

IronPDF で Interlocked を実装する

C#でのInterlockedの基本的な使用法

Interlocked クラスは、変数に対してアトミック操作を行うためのいくつかのメソッドを提供します。

  • 加算: 2つの整数を加算し、結果を変数に格納します。
  • CompareExchange: 2 つの値を等しいかどうか比較し、等しい場合はそのうちの 1 つの値を置き換えます。
  • インクリメント: int値を1増やし、新しい値を返します。
  • デクリメント: int 値を1減らし、新しい値を返します。

    たとえば、マルチスレッド環境で共有カウンターを安全にインクリメントする必要がある場合は、Interlocked.Incrementを使用します。

int counter = 0;
Interlocked.Increment(ref counter);
int counter = 0;
Interlocked.Increment(ref counter);
Dim counter As Integer = 0
Interlocked.Increment(counter)
$vbLabelText   $csharpLabel

これにより、複数のスレッドが同時に変更している場合でも、安全にカウンターがインクリメントされることが保証されます。

IronPDFとC#インターロックを使用したスレッドセーフPDF生成

IronPDFでInterlockedをマルチスレッドコンテキストで使用する実践的な例を見てみましょう。 複数のスレッドでPDFファイルを生成しており、各スレッドに固有の識別子またはページ番号を持たせる必要があるとします。

これを実装する方法は次のとおりです:

using IronPdf;
using System;
using System.Threading;
class Program
{
    static int pageCount = 0;
    static readonly object lockObject = new object(); // Object for locking
    static void Main()
    {
        var threads = new Thread[5];
        List<PdfDocument> pdfList = new List<PdfDocument>();
        // Create threads for parallel PDF generation
        for (int i = 0; i < threads.Length; i++)
        {
            threads[i] = new Thread(() => GeneratePdf(pdfList));
            threads[i].Start();
        }
        // Wait for all threads to complete
        foreach (var thread in threads)
        {
            thread.Join();
        }
        // Merge all the generated PDFs
        PdfDocument finalPdf = pdfList[0]; // Start with the first document
        // Merge remaining PDFs into finalPdf
        for (int i = 1; i < pdfList.Count; i++)
        {
            finalPdf = PdfDocument.Merge(finalPdf, pdfList[i]);
        }
        // Save the merged PDF
        finalPdf.SaveAs("MergedGeneratedPDF.pdf");
        Console.WriteLine("All PDFs merged and saved successfully.");
    }
    static void GeneratePdf(List<PdfDocument> pdfList)
    {
        // Use ChromePdfRenderer instead of HtmlToPdf
        ChromePdfRenderer renderer = new ChromePdfRenderer();
        // Use Interlocked to ensure unique page number per thread and using a "ref object" to reference the pageCount object 
        int pageNum = Interlocked.Increment(ref pageCount);
        // Generate a PDF page using ChromePdfRenderer
        var pdfPage = renderer.RenderHtmlAsPdf($"Page {pageNum} generated by thread {Thread.CurrentThread.ManagedThreadId}");
        // Add generated PDF page to the list (thread-safe)
        lock (lockObject) // Ensure thread-safety when adding to shared list
        {
            pdfList.Add(pdfPage);
        }
        string fileName = $"GeneratedPDF_{pageNum}.pdf";
        pdfPage.SaveAs(fileName);
        Console.WriteLine($"Thread {Thread.CurrentThread.ManagedThreadId} generated: {fileName}");
    }
}
using IronPdf;
using System;
using System.Threading;
class Program
{
    static int pageCount = 0;
    static readonly object lockObject = new object(); // Object for locking
    static void Main()
    {
        var threads = new Thread[5];
        List<PdfDocument> pdfList = new List<PdfDocument>();
        // Create threads for parallel PDF generation
        for (int i = 0; i < threads.Length; i++)
        {
            threads[i] = new Thread(() => GeneratePdf(pdfList));
            threads[i].Start();
        }
        // Wait for all threads to complete
        foreach (var thread in threads)
        {
            thread.Join();
        }
        // Merge all the generated PDFs
        PdfDocument finalPdf = pdfList[0]; // Start with the first document
        // Merge remaining PDFs into finalPdf
        for (int i = 1; i < pdfList.Count; i++)
        {
            finalPdf = PdfDocument.Merge(finalPdf, pdfList[i]);
        }
        // Save the merged PDF
        finalPdf.SaveAs("MergedGeneratedPDF.pdf");
        Console.WriteLine("All PDFs merged and saved successfully.");
    }
    static void GeneratePdf(List<PdfDocument> pdfList)
    {
        // Use ChromePdfRenderer instead of HtmlToPdf
        ChromePdfRenderer renderer = new ChromePdfRenderer();
        // Use Interlocked to ensure unique page number per thread and using a "ref object" to reference the pageCount object 
        int pageNum = Interlocked.Increment(ref pageCount);
        // Generate a PDF page using ChromePdfRenderer
        var pdfPage = renderer.RenderHtmlAsPdf($"Page {pageNum} generated by thread {Thread.CurrentThread.ManagedThreadId}");
        // Add generated PDF page to the list (thread-safe)
        lock (lockObject) // Ensure thread-safety when adding to shared list
        {
            pdfList.Add(pdfPage);
        }
        string fileName = $"GeneratedPDF_{pageNum}.pdf";
        pdfPage.SaveAs(fileName);
        Console.WriteLine($"Thread {Thread.CurrentThread.ManagedThreadId} generated: {fileName}");
    }
}
Imports IronPdf
Imports System
Imports System.Threading
Friend Class Program
	Private Shared pageCount As Integer = 0
	Private Shared ReadOnly lockObject As New Object() ' Object for locking
	Shared Sub Main()
		Dim threads = New Thread(4){}
		Dim pdfList As New List(Of PdfDocument)()
		' Create threads for parallel PDF generation
		For i As Integer = 0 To threads.Length - 1
			threads(i) = New Thread(Sub() GeneratePdf(pdfList))
			threads(i).Start()
		Next i
		' Wait for all threads to complete
		For Each thread In threads
			thread.Join()
		Next thread
		' Merge all the generated PDFs
		Dim finalPdf As PdfDocument = pdfList(0) ' Start with the first document
		' Merge remaining PDFs into finalPdf
		For i As Integer = 1 To pdfList.Count - 1
			finalPdf = PdfDocument.Merge(finalPdf, pdfList(i))
		Next i
		' Save the merged PDF
		finalPdf.SaveAs("MergedGeneratedPDF.pdf")
		Console.WriteLine("All PDFs merged and saved successfully.")
	End Sub
	Private Shared Sub GeneratePdf(ByVal pdfList As List(Of PdfDocument))
		' Use ChromePdfRenderer instead of HtmlToPdf
		Dim renderer As New ChromePdfRenderer()
		' Use Interlocked to ensure unique page number per thread and using a "ref object" to reference the pageCount object 
		Dim pageNum As Integer = Interlocked.Increment(pageCount)
		' Generate a PDF page using ChromePdfRenderer
		Dim pdfPage = renderer.RenderHtmlAsPdf($"Page {pageNum} generated by thread {Thread.CurrentThread.ManagedThreadId}")
		' Add generated PDF page to the list (thread-safe)
		SyncLock lockObject ' Ensure thread-safety when adding to shared list
			pdfList.Add(pdfPage)
		End SyncLock
		Dim fileName As String = $"GeneratedPDF_{pageNum}.pdf"
		pdfPage.SaveAs(fileName)
		Console.WriteLine($"Thread {Thread.CurrentThread.ManagedThreadId} generated: {fileName}")
	End Sub
End Class
$vbLabelText   $csharpLabel

コードの説明

このC#プログラムは、スレッドを使用して複数のPDFを並行して生成し、その後IronPDFを使用して単一のPDFに結合します。

  1. マルチスレッド: 5つのスレッドが作成され、同時にPDFを生成します。 各スレッドは、Interlocked.Increment を使用して一意のページ番号を取得します。

  2. スレッドセーフティ: 共有された pdfList へのアクセスは、PDF をリストに追加する際の競合状態を防ぐために、lock ステートメントで同期されています。

  3. PDFの結合: すべてのスレッドが終了した後、pdfList 内のPDFは順次 PdfDocument.Merge を使用して結合され、最終的なPDFが保存されます。

  4. 同期: メインスレッドは、スレッドのマージに進む前に、すべてのスレッドが完了するのを thread.Join() を使用して待ちます。

コンソール出力

C# インターロック(開発者向けの動作方法):図 2 - C# インターロックを使用したスレッドセーフな PDF 生成のコンソール出力

Pixabay から追加アップロード

またはここに画像をドラッグアンドドロップします

代替テキストをクリア

PDF出力

C# Interlocked(開発者向けの仕組み):図3 - C# Interlocked を使用したスレッドセーフなPDF生成のPDF出力

Pixabay から追加アップロード

またはここに画像をドラッグアンドドロップします

代替テキストをクリア

なぜこれはスレッドセーフなのか

  • スレッドセーフなリストの変更: lock を使用することで、共有されている pdfList の変更が安全に行われ、複数のスレッドが同時にリストに追加してレースコンディションを引き起こすのを防ぎます。
  • 非同期コードは不要: コードは非同期/待機を必要としません。なぜなら、操作は連続しており、長時間実行されるI/Oやネットワーク呼び出しを含まないからです。 ここでの主な懸念は、共有データ(リスト)へのアクセスが適切に同期されていることを保証することです。

エラーハンドリングとパフォーマンスに関する考慮事項

マルチスレッドコードを扱う際、エラーハンドリングとパフォーマンス最適化は不可欠です。

  • エラーハンドリング:Interlockedはスレッドセーフティを保証しますが、PDF生成ロジック内の潜在的なエラーを管理する必要があります。 try-catchブロックを使用して、例外を優雅に処理できます:
try
{
    finalPdf.SaveAs(fileName);
}
catch (Exception ex)
{
    Console.WriteLine($"Error generating PDF: {ex.Message}");
}
try
{
    finalPdf.SaveAs(fileName);
}
catch (Exception ex)
{
    Console.WriteLine($"Error generating PDF: {ex.Message}");
}
Try
	finalPdf.SaveAs(fileName)
Catch ex As Exception
	Console.WriteLine($"Error generating PDF: {ex.Message}")
End Try
$vbLabelText   $csharpLabel
  • パフォーマンスに関する考慮事項:Interlockedはアトミック操作に最適化されていますが、過度な同期はオーバーヘッドを引き起こす可能性があります。 高い同時操作量を処理している場合、競合を減らすために同期を最も重要な共有変数に最小限に抑えるべきです。

結論

スレッドセーフティは、カウンターやリストのような共有リソースを扱う際、特にマルチスレッドアプリケーションにおいて非常に重要です。 IronPDFを使用してPDFを作成または操作する際に、Interlockedを統合することで、操作がスレッドセーフで信頼性のあるものとなります。

InterlockedをIronPDFと組み合わせて使用することで、.NET開発者はデータの整合性を保ちながら、PDF処理ワークフローを効率的にスケーリングすることができます。 レポートの生成、ドキュメントのマージ、または複雑なPDF操作を並行して実行する際、Interlockedは一貫性を保ち、競合状態を避けるのに役立ちます。

これらのベストプラクティスにより、IronPDFの機能をフルに活用して、マルチスレッドPDFワークフローを効率的かつ堅牢にすることができます。IronPDFを本日から統合し、その強力なPDF作成と操作機能を直接体験する準備はできていますか!

チペゴ
ソフトウェアエンジニア
チペゴは優れた傾聴能力を持ち、それが顧客の問題を理解し、賢明な解決策を提供する助けとなっています。彼は情報技術の学士号を取得後、2023年にIron Softwareチームに加わりました。現在、彼はIronPDFとIronOCRの2つの製品に注力していますが、顧客をサポートする新しい方法を見つけるにつれて、他の製品に関する知識も日々成長しています。Iron Softwareでの協力的な生活を楽しんでおり、さまざまな経験を持つチームメンバーが集まり、効果的で革新的な解決策を提供することに貢献しています。チペゴがデスクを離れているときは、良い本を楽しんだり、サッカーをしていることが多いです。
次へ >
C# 文字列メソッド(開発者向けの動作方法)