跳過到頁腳內容
.NET HELP

C# Event Handler (How it Works for Developers)

在現代 .NET 應用程式中,事件驅動程式設計在提高回應速度和確保流暢的使用者體驗方面發揮著至關重要的作用。 當像產生 PDF 這樣的任務需要時間時,你不希望阻塞主執行緒。 相反,您可以使用事件處理程序非同步運行任務,並在事件發生時做出反應,從而使您的應用程式更具互動性和響應性。

在本指南中,我們將向您展示如何將 C# 事件處理方法與IronPDF集成,從而在桌面和 Web 環境中實現無縫的 PDF 工作流程。 無論您使用的是 WinForms、WPF 還是任何其他基於 C# 程式語言的平台,本指南都將為您提供協助。

設定您的 IronPDF 項目

在深入探討事件處理之前,讓我們先在 .NET 專案中快速設定 IronPDF。

透過 NuGet 安裝 IronPDF

在 Visual Studio 的套件管理器控制台中執行:

Install-Package IronPdf

這將安裝使用 IronPDF 產生 PDF 所需的一切。

使用 IronPDF 產生基本 PDF 文件

以下是一個簡單的範例,用於驗證 IronPDF 是否正常運作:

using IronPdf;
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf("<h1>Hello from IronPDF!</h1>");
pdf.SaveAs("example.pdf");
using IronPdf;
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf("<h1>Hello from IronPDF!</h1>");
pdf.SaveAs("example.pdf");
Imports IronPdf
Private renderer = New ChromePdfRenderer()
Private pdf = renderer.RenderHtmlAsPdf("<h1>Hello from IronPDF!</h1>")
pdf.SaveAs("example.pdf")
$vbLabelText   $csharpLabel

一旦此功能正常運作,您就可以新增事件欄位、連接已註冊的委託人,並使用委託類型建立事件驅動的工作流程。

針對 .NET 開發人員的 C# 事件處理程序基礎知識

事件驅動程式設計基礎

透過事件驅動編程,您的應用程式會在事件發生時做出回應,例如 PDF 生成完成時。 C# 使用委託作為類型安全的函數指針,讓您定義應用程式應該如何回應。

通常情況下,您可以使用 event 關鍵字聲明事件,將它們連接到事件處理方法,並使用自訂 EventArgs 子類別傳遞資料。

使用事件關鍵字聲明事件

C# 使用 event 關鍵字宣告事件成員。 例如:

public event EventHandler PdfGenerated;
public event EventHandler PdfGenerated;
Public Event PdfGenerated As EventHandler
$vbLabelText   $csharpLabel

此行聲明了一個名為 PdfGenerated 的事件欄位。 它使用 EventHandler,這是一個內建委託,具有以下參數列表:(物件 sender,EventArgs e)——這通常被稱為 .NET 中事件的命名模式。

在 C# 中定義和訂閱事件

使用委託向事件新增方法

C# 事件支援使用 += 語法在執行時間動態新增方法。 方法如下:

pdfService.PdfGenerated += (s, e) =>
{
    Console.WriteLine("PDF was generated!");
};
pdfService.PdfGenerated += (s, e) =>
{
    Console.WriteLine("PDF was generated!");
};
AddHandler pdfService.PdfGenerated, Sub(s, e)
	Console.WriteLine("PDF was generated!")
End Sub
$vbLabelText   $csharpLabel

此訂閱者類別監聽 PdfGenerated 事件,並在觸發時執行方法呼叫。

自訂事件數據

若要傳遞事件資料(例如產生的檔案路徑),請定義一個從 EventArgs 衍生出來的類別:

public class PdfGeneratedEventArgs : EventArgs
{
    public string FilePath { get; set; } // returned value
}
public class PdfGeneratedEventArgs : EventArgs
{
    public string FilePath { get; set; } // returned value
}
Public Class PdfGeneratedEventArgs
	Inherits EventArgs

	Public Property FilePath() As String ' -  returned value
End Class
$vbLabelText   $csharpLabel

然後使用通用委託類型重新定義事件:

public event EventHandler<PdfGeneratedEventArgs> PdfGenerated;
public event EventHandler<PdfGeneratedEventArgs> PdfGenerated;
Public Event PdfGenerated As EventHandler(Of PdfGeneratedEventArgs)
$vbLabelText   $csharpLabel

這樣,當事件發生時,您就可以獲得結構化的、類型安全的數據,從而使您的回應邏輯更加強大。

處理多個事件

您可以定義多個事件:

public event EventHandler PdfGenerationStarted;
public event EventHandler<PdfGeneratedEventArgs> PdfGenerationCompleted;
public event EventHandler PdfGenerationStarted;
public event EventHandler<PdfGeneratedEventArgs> PdfGenerationCompleted;
Public Event PdfGenerationStarted As EventHandler
Public Event PdfGenerationCompleted As EventHandler(Of PdfGeneratedEventArgs)
$vbLabelText   $csharpLabel

每個事件欄位都由一個訂閱者類別處理,從而允許每個階段採用不同的事件處理方法。 這種關注點分離的做法在複雜的工作流程中是合理的。

在 IronPDF 中使用事件處理程序

產生大型 PDF 時,最好在背景執行緒上執行 IronPDF,並在完成後通知 UI。 以下是事件驅動型設計如何提供協助:

  • 使用BackgroundWorker非同步產生 PDF 文件
  • 在每個階段完成後觸發事件。
  • 使用事件資料物件傳遞結果數據

程式碼範例 – 非同步生成 PDF

以下範例是使用 IronPDF 進行事件處理的完整程式碼:

using System;
using System.ComponentModel;
using IronPdf;
namespace IronPdfEventHandlerExample
{
    // 1. Define custom EventArgs to carry event data
    public class PdfGeneratedEventArgs : EventArgs
    {
        public string FilePath { get; set; }
    }
    // 2. Main class with event, BackgroundWorker, and logic
    public class PdfGenerator
    {
        // Declare the public event using EventHandler<T>
        public event EventHandler<PdfGeneratedEventArgs> PdfGenerated;
        private readonly BackgroundWorker _worker;
        public PdfGenerator()
        {
            _worker = new BackgroundWorker();
            _worker.DoWork += OnDoWork;
            _worker.RunWorkerCompleted += OnRunWorkerCompleted;
        }
        // Start the async operation
        public void GenerateAsync(string html, string outputPath)
        {
            _worker.RunWorkerAsync(new Tuple<string, string>(html, outputPath));
        }
        // Perform PDF generation in background
        private void OnDoWork(object sender, DoWorkEventArgs e)
        {
            var (html, path) = (Tuple<string, string>)e.Argument;
            var renderer = new HtmlToPdf();
            var pdf = renderer.RenderHtmlAsPdf(html);
            pdf.SaveAs(path);
            e.Result = path;
        }
        // Notify subscribers when the PDF is ready
        private void OnRunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            var path = e.Result as string;
            PdfGenerated?.Invoke(this, new PdfGeneratedEventArgs { FilePath = path });
        }
    }
    // 3. Program to wire it all together
    class Program
    {
        public static void Main(string[] args)
        {
            var generator = new PdfGenerator();
            // Subscribe to the PdfGenerated event
            generator.PdfGenerated += OnPdfGenerated;
            Console.WriteLine("Generating PDF asynchronously...");
            generator.GenerateAsync("<h1>Hello, IronPDF!</h1>", "output.pdf");
            Console.WriteLine("Press any key to exit after generation.");
            Console.ReadKey();
        }
        // Event handler for when the PDF is ready
        static void OnPdfGenerated(object sender, PdfGeneratedEventArgs e)
        {
            Console.WriteLine($"PDF generated at: {e.FilePath}");
        }
    }
}
using System;
using System.ComponentModel;
using IronPdf;
namespace IronPdfEventHandlerExample
{
    // 1. Define custom EventArgs to carry event data
    public class PdfGeneratedEventArgs : EventArgs
    {
        public string FilePath { get; set; }
    }
    // 2. Main class with event, BackgroundWorker, and logic
    public class PdfGenerator
    {
        // Declare the public event using EventHandler<T>
        public event EventHandler<PdfGeneratedEventArgs> PdfGenerated;
        private readonly BackgroundWorker _worker;
        public PdfGenerator()
        {
            _worker = new BackgroundWorker();
            _worker.DoWork += OnDoWork;
            _worker.RunWorkerCompleted += OnRunWorkerCompleted;
        }
        // Start the async operation
        public void GenerateAsync(string html, string outputPath)
        {
            _worker.RunWorkerAsync(new Tuple<string, string>(html, outputPath));
        }
        // Perform PDF generation in background
        private void OnDoWork(object sender, DoWorkEventArgs e)
        {
            var (html, path) = (Tuple<string, string>)e.Argument;
            var renderer = new HtmlToPdf();
            var pdf = renderer.RenderHtmlAsPdf(html);
            pdf.SaveAs(path);
            e.Result = path;
        }
        // Notify subscribers when the PDF is ready
        private void OnRunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            var path = e.Result as string;
            PdfGenerated?.Invoke(this, new PdfGeneratedEventArgs { FilePath = path });
        }
    }
    // 3. Program to wire it all together
    class Program
    {
        public static void Main(string[] args)
        {
            var generator = new PdfGenerator();
            // Subscribe to the PdfGenerated event
            generator.PdfGenerated += OnPdfGenerated;
            Console.WriteLine("Generating PDF asynchronously...");
            generator.GenerateAsync("<h1>Hello, IronPDF!</h1>", "output.pdf");
            Console.WriteLine("Press any key to exit after generation.");
            Console.ReadKey();
        }
        // Event handler for when the PDF is ready
        static void OnPdfGenerated(object sender, PdfGeneratedEventArgs e)
        {
            Console.WriteLine($"PDF generated at: {e.FilePath}");
        }
    }
}
Imports System
Imports System.ComponentModel
Imports IronPdf
Namespace IronPdfEventHandlerExample
	' 1. Define custom EventArgs to carry event data
	Public Class PdfGeneratedEventArgs
		Inherits EventArgs

		Public Property FilePath() As String
	End Class
	' 2. Main class with event, BackgroundWorker, and logic
	Public Class PdfGenerator
		' Declare the public event using EventHandler<T>
		Public Event PdfGenerated As EventHandler(Of PdfGeneratedEventArgs)
		Private ReadOnly _worker As BackgroundWorker
		Public Sub New()
			_worker = New BackgroundWorker()
			AddHandler _worker.DoWork, AddressOf OnDoWork
			AddHandler _worker.RunWorkerCompleted, AddressOf OnRunWorkerCompleted
		End Sub
		' Start the async operation
		Public Sub GenerateAsync(ByVal html As String, ByVal outputPath As String)
			_worker.RunWorkerAsync(New Tuple(Of String, String)(html, outputPath))
		End Sub
		' Perform PDF generation in background
		Private Sub OnDoWork(ByVal sender As Object, ByVal e As DoWorkEventArgs)
'INSTANT VB TODO TASK: VB has no equivalent to C# deconstruction declarations:
			var(html, path) = (Tuple(Of String, String))e.Argument
			Dim renderer = New HtmlToPdf()
			Dim pdf = renderer.RenderHtmlAsPdf(html)
			pdf.SaveAs(path)
			e.Result = path
		End Sub
		' Notify subscribers when the PDF is ready
		Private Sub OnRunWorkerCompleted(ByVal sender As Object, ByVal e As RunWorkerCompletedEventArgs)
			Dim path = TryCast(e.Result, String)
			RaiseEvent PdfGenerated(Me, New PdfGeneratedEventArgs With {.FilePath = path})
		End Sub
	End Class
	' 3. Program to wire it all together
	Friend Class Program
		Public Shared Sub Main(ByVal args() As String)
			Dim generator = New PdfGenerator()
			' Subscribe to the PdfGenerated event
			AddHandler generator.PdfGenerated, AddressOf OnPdfGenerated
			Console.WriteLine("Generating PDF asynchronously...")
			generator.GenerateAsync("<h1>Hello, IronPDF!</h1>", "output.pdf")
			Console.WriteLine("Press any key to exit after generation.")
			Console.ReadKey()
		End Sub
		' Event handler for when the PDF is ready
		Private Shared Sub OnPdfGenerated(ByVal sender As Object, ByVal e As PdfGeneratedEventArgs)
			Console.WriteLine($"PDF generated at: {e.FilePath}")
		End Sub
	End Class
End Namespace
$vbLabelText   $csharpLabel

控制台輸出

C# 事件處理程序(開發者運作方式):圖 1 - 控制台輸出

PDF 輸出

C# 事件處理程序(開發人員工作原理):圖 2 - PDF 輸出

此程式碼的主要特性

  • public event EventHandler<PdfGeneratedEventArgs>聲明一個強類型事件
  • PdfGeneratedEventArgs :事件資料的自訂類
  • BackgroundWorker :允許非同步執行,避免 UI 阻塞
  • ?.Invoke(...) : 安全事件調用
  • Tuple<string, string>將 HTML 和輸出路徑傳遞給後台執行緒

.NET 事件處理技巧

1.避免 UI 執行緒阻塞

使用 RunWorkerCompleted 等事件處理程序,僅在背景任務完成後執行 UI 更新。

2.優雅地處理異常

將你的工作邏輯用 try-catch 區塊包裹在 DoWork 中,並透過 e.Error 將異常傳遞給 RunWorkerCompleted。

if (e.Error != null)
{
    MessageBox.Show("Error: " + e.Error.Message);
}
if (e.Error != null)
{
    MessageBox.Show("Error: " + e.Error.Message);
}
If e.Error IsNot Nothing Then
	MessageBox.Show("Error: " & e.Error.Message)
End If
$vbLabelText   $csharpLabel

3.必要時取消訂閱

對於長時間運行的應用程序,當不再需要某些事件時,應取消訂閱這些事件,以避免記憶體洩漏:

pdfWorker.DoWork -= PdfWorker_DoWork;
pdfWorker.DoWork -= PdfWorker_DoWork;
pdfWorker.DoWork -= PdfWorker_DoWork
$vbLabelText   $csharpLabel

最後想說的話

將事件處理程序、委託類型和事件欄位與 IronPDF 結合使用,可以為 .NET 應用程式增添響應迅速、現代化的優勢。 無論您是在基底類別中產生文件、在衍生類別中建立可重複使用邏輯,還是僅僅探索 .NET 的事件模型,這種模式都具有可擴展性和簡潔性。

何時使用這種方法

  • 您希望在任務完成時觸發一個事件 你需要將邏輯和使用者介面清晰地分開。
  • 您正在使用BackgroundWorker 、事件和委託
  • 你喜歡 C# 的型別安全函數點機制

可探索的替代方案

  • 為較新的工作流程提供async/awaitTask.Run
  • IProgress對於長時間運行期間的即時更新,IronPDF 與 C# 事件相結合,可以輕鬆創建功能強大、響應迅速的 PDF 生成應用程序,並充分考慮實際應用場景。 準備在您的 .NET 應用程式中實現事件驅動的 PDF 生成嗎?立即試用IronPDF 免費試用版,讓您的使用者享受流暢、無阻塞的體驗!

常見問題解答

如何在 C# 中將 HTML 轉換為 PDF?

您可以使用 IronPDF 的 RenderHtmlAsPdf 方法將 HTML 字串轉換成 PDF。您也可以使用 RenderHtmlFileAsPdf 將 HTML 檔案轉換成 PDF。

為什麼事件驅動程式設計在 .NET 應用程式中很重要?

事件驅動程式設計在 .NET 應用程式中非常重要,可讓任務在不阻塞主線程下以非同步方式執行,從而改善反應速度並確保順暢的使用者體驗。

如何在 .NET 專案中安裝必要的 PDF 產生工具?

您可以透過 NuGet 安裝 IronPDF,方法是在 Visual Studio 的套件管理員控制台執行「Install-Package IronPdf」指令。

如何在 C# 中宣告事件?

在 C# 中,事件是使用「事件」關鍵字來宣告的,通常會搭配類似「EventHandler」的委託類型。例如public event EventHandler PdfGenerated;

C# 事件處理中的 delegate 是什麼?

C# 中的 delegate 是一種類型安全的函數指標,可讓您定義可回應事件而呼叫的方法。

如何在 C# 中為事件新增方法?

您可以在 C# 中使用「+="語法在執行時動態地為事件新增方法,以訂閱事件。

建立自訂 EventArgs 類的目的是什麼?

使用自訂的 EventArgs 類別,以結構化和類型安全的方式,將特定於事件的資料 (例如檔案路徑) 傳送給事件處理程式。

為什麼要使用 BackgroundWorker 來產生大型 PDF?

使用 BackgroundWorker 可讓您以非同步方式執行 PDF 生成任務,防止 UI 阻塞並改善使用者體驗。

在 .NET 中使用事件有哪些技巧?

主要秘訣包括避免 UI 線程阻塞,方法是在背景任務完成後才更新 UI、優雅地處理異常,以及在不再需要時取消訂閱事件以防止記憶體洩漏。

除了在 .NET 中使用事件處理器之外,還有哪些替代方法?

替代方案包括使用 async/await 和 Task.Run 來處理較新的工作流程,以及使用 IProgress 來處理長時間作業期間的即時更新。

Jacob Mellor,技術長 @ Team Iron
首席技術長

Jacob Mellor 是 Iron Software 的首席技術長,也是開創 C# PDF 技術的有遠見的工程師。作為 Iron Software 核心程式碼庫背後的原始開發人員,他從公司成立之初就塑造了公司的產品架構,與首席執行官 Cameron Rimington 一起將公司轉型為一家 50 多人的公司,為 NASA、Tesla 和全球政府機構提供服務。

Jacob 持有曼徹斯特大學土木工程一級榮譽工程學士學位 (BEng)(1998-2001 年)。

Jacob 於 1999 年在倫敦開設了他的第一家軟體公司,並於 2005 年創建了他的第一個 .NET 元件,之後,他專門解決微軟生態系統中的複雜問題。

他的旗艦產品 IronPDF & Iron Suite for .NET 函式庫在全球的 NuGet 安裝量已超過 3000 萬次,他的基礎程式碼持續為全球使用的開發人員工具提供動力。Jacob 擁有 25 年的商業經驗和 41 年的編碼專業知識,他一直專注於推動企業級 C#、Java 和 Python PDF 技術的創新,同時指導下一代的技術領導者。