.NET 幫助

C# Interlocked(如何為開發人員工作)

Chipego
奇佩戈·卡林达
2025年4月3日
分享:

在處理多執行緒應用程式時,確保執行緒安全是防止競爭條件和資料損毀的一個關鍵因素。 在使用IronPDF的PDF處理世界中,這個問題也不例外。 無論您是在生成、操作還是合併 PDF,如果未能保持適當的同步,並行運行這些任務可能會導致意外結果。 這就是 C# 的 Interlocked 類別 發揮作用的地方,為在多執行緒環境中確保執行緒安全操作提供了一種簡單而有效的方式。

什麼是 C# Interlocked 類別?

在C#中,Interlocked類提供了針對多個執行緒共用的變數進行原子操作的方法。 這可確保一個線程的操作不會受到其他線程的干擾,這對於需要保證操作在受控和一致的方式下執行時至關重要。 另一方面,IronPDF 是一個強大的函式庫,允許 .NET 開發人員創建、編輯和操作 PDF 文件。

當您將兩者結合使用時——Interlocked 用於執行緒安全與 IronPDF 用於 PDF 操作——您將獲得一個強大的解決方案,可在並行程式設計中處理 PDF 任務。 但是這是如何運作的,為什麼你應該關心呢? 讓我們更深入地探討 Interlocked 在 IronPDF 處理中的角色。

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?

執行緒安全性和併發性

在多线程应用程式中,多个线程可能会同时尝试访问和修改共享数据。 如果没有适当的同步,就可能导致问题,如竞态条件,其中两个线程试图同时更新相同的数据。 這可能導致無法預測的結果和難以調試的錯誤。

Interlocked 類別確保這些並發操作以原子方式處理。 換句話說,當您使用 Interlocked 修改物件的值時,改變會以單一、不可中斷的操作發生,這消除了競爭條件的風險。

在IronPDF的上下文中,許多PDF處理任務——例如添加頁面、編輯內容或從多個來源生成PDF——都非常適合並行處理。 如果不进行同步,並行執行這些操作可能會導致PDF文件損壞或在處理期間出錯。 使用 Interlocked 可以確保這些操作在多執行緒環境下仍然是安全的。

使用 Interlocked 與不同數據類型

當處理不同資料類型的變數時,可以使用 Interlocked 以安全地管理並發更新。 讓我們來探索一些您可能遇到的數據類型:

  • 浮點值:當操作需要引用類型時,可以使用 Interlocked.CompareExchange 方法與浮點值一起使用。
  • 原始值:在執行更新時,重要的是先處理原始值再進行更改,以確保執行緒操作的一致性。
  • Public static class:您可以創建一個公共靜態類來封裝你的 Interlocked 操作,使您的代碼更具模組化並更易於維護。
  • 雙精度值:Interlocked 不直接支援雙精度值,因為雙精度值不是整數類型,而原子操作是為整數優化的。 如果您需要對 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

何時將 Interlocked 用於 IronPDF

在多個執行緒處理共享資源的任何情況下,您應該使用 Interlocked。 範例包括:

  • 在 PDF 生成中追蹤頁碼。
  • 管理由多個線程訪問和修改的計數器或列表。

    通過使用 Interlocked 進行這些操作,您可以確保更新是線程安全的,從而防止衝突並確保數據完整性。

使用 IronPDF 實現 Interlocked

Interlocked 在 C# 中的基本用法

Interlocked 類別提供多種方法來對變數執行原子操作,例如:

  • 相加:將兩個整數相加並將結果存儲在一個變數中。
  • CompareExchange:比較兩個值是否相等,如果相等,則替換其中一個值。
  • 增量: 將一個整數值增加一並返回新值。
  • 遞減:將整數值減一並返回新值。

    例如,如果您需要在多線程環境中安全地增加一個共享計數器,請使用 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# Interlocked 的執行緒安全 PDF 生成

讓我們來看看在多執行緒環境中將Interlocked與IronPDF結合使用的實用範例。 假設您正在並行執行緒中生成 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 新增到列表時發生競爭條件。

  3. 合併PDF:當所有執行緒完成後,pdfList中的PDF將使用PdfDocument.Merge按順序合併,並保存最終的PDF。

  4. 同步:主執行緒在繼續合併之前,使用 thread.Join() 等待所有執行緒完成。

控制台輸出

C# Interlocked(對開發人員的運作方式):圖 2 - 使用 C# Interlocked 產生線程安全的 PDF 的控制台輸出

從Pixabay添加上傳

或將圖片拖放到此處

清除替代文字

PDF輸出

C# Interlocked(為開發人員運作的方式):圖 3 - 使用 C# Interlocked 生成具備執行緒安全性的 PDF 輸出

從Pixabay添加上傳

或將圖片拖放到此處

清除替代文字

為什麼這是執行緒安全的

  • 線程安全列表修改:使用鎖定確保對共享 pdfList 的修改是安全的,防止多個線程同時向列表添加而導致競爭條件。
  • 不需要非同步程式碼:由於操作是順序執行且不涉及長時間運行的 I/O 或網路呼叫,因此程式碼不需要使用 async/await。 主要的關注點是確保對共享數據(列表)的訪問得到正確的同步。

錯誤處理及效能考量

在處理多執行緒程式碼時,錯誤處理和性能優化是必不可少的。

  • 錯誤處理:儘管 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創建和操作功能!

Chipego
奇佩戈·卡林达
軟體工程師
Chipego 擁有天生的傾聽技能,這幫助他理解客戶問題,並提供智能解決方案。他在獲得信息技術理學學士學位後,于 2023 年加入 Iron Software 團隊。IronPDF 和 IronOCR 是 Chipego 專注的兩個產品,但隨著他每天找到新的方法來支持客戶,他對所有產品的了解也在不斷增長。他喜歡在 Iron Software 的協作生活,公司內的團隊成員從各自不同的經歷中共同努力,創造出有效的創新解決方案。當 Chipego 離開辦公桌時,他常常享受讀好書或踢足球的樂趣。
下一個 >
C# 字串方法(開發人員如何運作)