// 1. 聲明委託類型(簽名)
public delegate void MyDelegate(string name);
// 2. 目標方法(匹配簽名)
public static void MyDelegateFunc(string name)
{
Console.WriteLine("Hello, {0}", name);
}
// 3. 實例化並調用
MyDelegate md = new MyDelegate(MyDelegateFunc);
md("sam1111"); // 輸出: Hello, sam1111
// 1. 事件參數類(可選,無參數用 EventArgs)
public class MyEventArgs : EventArgs
{
public string Message { get; set; }
}
// 2. 事件處理器委託
public delegate void MyEventHandler(object sender, MyEventArgs e);
// 3. 發布者類
public class Publisher
{
public event MyEventHandler MyEvent;
protected virtual void OnMyEvent(MyEventArgs e)
{
MyEvent?.Invoke(this, e); // C# 6+ null 條件調用
}
public void DoWork()
{
// ... 業務邏輯 ...
OnMyEvent(new MyEventArgs { Message = "Completed" });
}
}
// 4. 訂閱者
public class Subscriber
{
public void Subscribe(Publisher pub)
{
pub.MyEvent += HandleEvent;
}
private void HandleEvent(object sender, MyEventArgs e)
{
Console.WriteLine($"Received: {e.Message}");
}
}
UI 執行緒啟動工作執行緒,通過事件回報進度:
public class TaskWorker
{
public event EventHandler ProgressChanged;
public event EventHandler Completed;
public void Start()
{
Task.Run(() =>
{
for (int i = 0; i <= 100; i += 10)
{
Thread.Sleep(100); // 模擬工作
ProgressChanged?.Invoke(this, new ProgressEventArgs(i));
}
Completed?.Invoke(this, new CompletedEventArgs(true));
});
}
}
// UI 端
var worker = new TaskWorker();
worker.ProgressChanged += (s, e) => progressBar.Value = e.Percent;
worker.Completed += (s, e) => MessageBox.Show("Done!");
worker.Start();
| 反模式 | 問題 | 正確做法 |
|---|---|---|
| 子窗口持有父窗口引用直接調用方法 | 雙向耦合,難維護、難測試 | 子窗口觸發事件,父窗口訂閱處理 |
| 事件處理器簽名不匹配 | 編譯錯誤或運行時異常 | 嚴格遵循 (object sender, EventArgs e) |
忘記取消訂閱 (-=) | 內存洩漏、重複執行 | 在 Dispose/Unload 中取消訂閱 |
Action<T>、Func<T, TResult> 減少自定義委託聲明BeginInvoke/EndInvoke 或 Task 結合事件