在事件調度(Event Dispatch)中,由於其他監聽器(listener)引發異常的情況是很常見的。當一個事件觸發時,其中一個監聽器拋出異常可能會導致整個事件鏈被中斷,影響其他監聽器的執行。這種情況下,使用適當的錯誤管理方法非常重要,以確保事件的穩定調度和其他監聽器的正常執行。
一個常見的錯誤管理方法是使用try-catch塊來捕獲可能引發異常的代碼段。在事件調度中,我們可以使用MulticastDelegate.GetInvocationList()方法獲取事件的監聽器列表,並在循環中逐個調用監聽器。通過將每個監聽器的調用放置在try-catch塊中,即使某個監聽器引發異常,也不會中斷整個事件的調度流程,保證其他監聽器能夠繼續執行。
讓我們看下面的示例來說明這一點:
public class Tester { public static event System.Action<string> EVENT_MyCallback; public void Method01_TriggerEvent() { // Don't do this, the exception will cause the other event listener fail. EVENT_MyCallback?.Invoke("Don't do this"); } public void Method02_TriggerEvent() { if (EVENT_MyCallback == null) return; var invList = EVENT_SceneLoaded.GetInvocationList(); foreach(var dispatcher in invList) { try { dispatcher.DynamicInvoke("Better"); } catch(System.Exception ex) { } } } }
Method01 是常見的懶人寫法, 需然正常情況是沒有問題的可是當 Event 越來越多 listener 監聽的時候就開始有問題了.
有問題的是地是 event dispatch 的順序是不被保
Method01_TriggerEvent是一種常見的懶惰寫法。在正常情況下是沒有問題的,但當事件的監聽器越來越多時,就會出現問題。問題出在事件調度的順序是不被保證的。
考慮以下示例:
public void OtherClass() { public OtherClass() { Tester.EVENT_MyCallback += Receive01; Tester.EVENT_MyCallback += Receive02; Tester.EVENT_MyCallback += Receive03; } private void Receive01(string msg) => Debug.Log(msg); private void Receive02(string msg) => throw System.Exception(); private void Receive03(string msg) => Debug.Log("M03"+ msg); }
當執行EVENT_MyCallback時,如果使用的是Method01_TriggerEvent,由於Receive02拋出異常,其他的Receive01和Receive03可能被忽略。但是,如果使用Method02_TriggerEvent,由於異常被try-catch捕獲,事件調度的foreach仍然會繼續執行,確保其他的Receive01和Receive03能夠正確接收調度。
通過適當的錯誤管理,我們能夠更好地處理異常情況,避免其對整個事件調度產生負面影響。這種做法有助於提高程序的可靠性和穩定性,確保事件的順利執行以及其他相關操作的正常進行。