Unity3D : Event dispatch 上其他 listener 的 Exception 處理

Unity3D : Event dispatch 上其他 listener 的 Exception 處理

在事件調度(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能夠正確接收調度。

通過適當的錯誤管理,我們能夠更好地處理異常情況,避免其對整個事件調度產生負面影響。這種做法有助於提高程序的可靠性和穩定性,確保事件的順利執行以及其他相關操作的正常進行。

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *

*

這個網站採用 Akismet 服務減少垃圾留言。進一步了解 Akismet 如何處理網站訪客的留言資料