跳過到頁腳內容
.NET幫助

C# 事件處理者(開發者工作方式)

在現代.NET應用程式中,事件驅動的程式設計在改善響應性和確保順暢的使用者體驗方面起著至關重要的作用。 當像PDF生成這樣的任務需要時間時,您不想阻塞主線程。 相反,您可以使用事件處理程序以非同步方式運行任務,並在事件發生後做出反應,讓您的應用程式更加互動和響應。

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

設置您的IronPDF專案

在進入事件處理之前,讓我們快速在您的.NET專案中設置IronPDF。

通過NuGet安裝IronPDF

在Visual Studio的Package Manager Console中運行:

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子類傳遞數據。

使用event關鍵字聲明事件

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

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

此行聲明了一個名為PdfGenerated的事件字段。 它使用EventHandler,一個內建的委託,具有以下參數列表:(object 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. 優雅地處理異常

在DoWork中將工作邏輯包裹在try-catch塊中,並通過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的事件模型,此模式都是可擴展且清晰的。

何時使用此方法

  • 當任務完成時想要觸發事件
  • 需要在邏輯和UI之間有乾淨的分離
  • 使用BackgroundWorker、事件和委託
  • 喜歡C#的類型安全函數指針機制

可探索的替代方案

  • 使用async/awaitTask.Run進行更新的工作流程
  • 在長操作期間使用IProgress<T>進行實時更新,IronPDF與C#事件的結合使創建強大而響應的PDF生成應用程式變得簡單,其實用性體現於現實世界中。 準備好在您的.NET應用中實施事件驅動的PDF生成了嗎? 使用IronPDF免費試用版嘗試一下,為您的用戶提供流暢、不會阻塞的體驗!

常見問題解答

怎樣在 C# 中將 HTML 轉換為 PDF?

您可以使用 IronPDF 的 RenderHtmlAsPdf 方法將 HTML 字符串轉換為 PDF。您還可以使用 RenderHtmlFileAsPdf 將 HTML 文件轉換為 PDF。

.NET應用程式中,事件驅動編程為何重要?

在.NET應用程式中,事件驅動編程很重要,因為它能提高響應速度,通過允許任務異步運行而不會阻塞主線程來確保流暢的用戶體驗。

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

您可以在Visual Studio的套件管理器控制台中運行命令 'Install-Package IronPdf',通過NuGet安裝IronPDF。

如何在C#中聲明事件?

在C#中,事件使用 'event' 關鍵字來聲明,通常使用像 'EventHandler' 這樣的委託類型。例如:public event EventHandler PdfGenerated;

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

C#中的委託是一種強類型的函數指針,允許您定義可以響應事件調用的方法。

如何在C#中將方法添加到事件中?

您可以在運行時動態地使用 '+=' 語法訂閱事件來將方法添加到事件中。

創建自定義EventArgs類的目的是什麼?

自定義EventArgs類用於以結構化和強類型的方式將事件特定數據(如文件路徑)傳遞給事件處理程序。

為何應該使用BackgroundWorker來生成大型PDF?

使用BackgroundWorker可以允許您異步運行PDF生成任務,防止UI阻塞並改善用戶體驗。

關於.NET中的事件操作,有哪些提示?

關鍵提示包括在後台任務完成後才更新UI以避免阻塞UI線程,優雅地處理異常,以及在不再需要時取消訂閱事件以防止記憶體洩漏。

.NET中使用事件處理程序的替代方法有哪些?

替代方法包括使用async/await和Task.Run來實現更新的工作流程,以及使用IProgress來在長時間操作期間進行實時更新。

Curtis Chau
技術作家

Curtis Chau 擁有卡爾頓大學計算機科學學士學位,專注於前端開發,擅長於 Node.js、TypeScript、JavaScript 和 React。Curtis 熱衷於創建直觀且美觀的用戶界面,喜歡使用現代框架並打造結構良好、視覺吸引人的手冊。

除了開發之外,Curtis 對物聯網 (IoT) 有著濃厚的興趣,探索將硬體和軟體結合的創新方式。在閒暇時間,他喜愛遊戲並構建 Discord 機器人,結合科技與創意的樂趣。