簡體   English   中英

在C#中引發事件,忽略處理程序引發的異常

[英]Raising events in C# that ignore exceptions raised by handlers

我在C#中引發事件的一個小問題是事件處理程序中的異常會破壞我的代碼,並且可能會阻止其他處理程序被調用,如果破壞的那個正好先被調用; 在大多數情況下,如果正在偵聽其事件的其他人的代碼被破壞,我的代碼就不會在意。

我創建了一個捕獲異常的擴展方法:

public static void Raise(this EventHandler eh, object sender, EventArgs e)
{
  if (eh == null)
    return;
  try
  {
    eh(sender, e);
  }
  catch { }
}

雖然這確實意味着我的代碼仍然存在,但是這種方法不會阻止第一個事件處理程序拋出異常並阻止第二個和后續處理程序被通知該事件。 我正在研究迭代GetInvocationList以將每個單獨的事件處理程序包裝在它自己的try / catch中的方法,但這似乎效率低下,而且我不確定最好的方法,或者即使我應該這樣做。

另外,我真的很不舒服,只是忽略了這里的例外(並且沒有FxCop / Resharper); 實際上,在這種情況下,例外應該發生什么?

您應該只捕獲可以處理的異常。 例如,您可能正在訪問文件但沒有足夠的權限。 如果你知道偶爾會發生這種情況,所有需要發生的事情就是記錄案例,然后單獨捕獲該異常

如果您的代碼無法處理異常,請不要捕獲它。

這是一個特例,所以很有可能其他事件處理程序也無法“做他們的東西”,所以讓它傳播到可以安全處理的級別。

如果事件處理程序沒有捕獲異常,我沒有看到任何可以在拋出事件的類中處理異常的好方法。 您沒有任何上下文來了解處理程序正在執行的操作。 在這種情況下讓應用程序崩潰是最安全的,因為您不知道其他事件處理程序可能導致哪些副作用可能會破壞您的應用程序的穩定性。 這里的教訓是事件處理程序必須是健壯的(處理它們自己的異常),因為觸發事件的類永遠不應該捕獲處理程序拋出的異常。

如果你這樣做了怎么辦?

public static void Raise(this EventHandler eh, object sender, EventArgs e)
{
    if (eh == null)
        return;

    foreach(var handler in eh.GetInvocationList().Cast<EventHandler>())
    {
        try
        {
            handler(sender, e);
        }
        catch { }
    }
}

一個簡單但重要的規則:

代碼中的每個缺陷都應盡可能早地致命。

通過這種方式,可以找到並修復錯誤,並且軟件變得越來越強大。 別人說的是對的; 永遠不要抓住你不期望的例外並且知道如何處理。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM