在C#中引发事件,忽略处理程序引发的异常

时间:2010-06-24 20:59:03

标签: c# events exception

我在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都没有);实际上,在这种情况下,例外会发生什么?

4 个答案:

答案 0 :(得分:3)

您应该只捕获可以处理的异常。例如,您可能正在访问文件但没有足够的权限。如果你知道偶尔会发生这种情况,那么所有需要发生的事情就是记录案例,然后单独捕获该例外

如果您的代码无法处理异常,请不要捕获它。

这是一个特例,所以很有可能其他事件处理程序也无法“做他们的东西”,所以让它传播到可以安全处理的水平。

答案 1 :(得分:3)

如果事件处理程序没有捕获异常,我没有看到任何可以在抛出事件的类中处理异常的好方法。您没有任何上下文来了解处理程序正在执行的操作。在这种情况下让应用程序崩溃是最安全的,因为您不知道其他事件处理程序可能导致哪些副作用可能会破坏您的应用程序的稳定性。这里的教训是事件处理程序必须是健壮的(处理它们自己的异常),因为触发事件的类永远不应该捕获处理程序抛出的异常。

答案 2 :(得分:3)

如果你这样做会怎么样?

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 { }
    }
}

答案 3 :(得分:2)

一条简单而重要的规则:

  

代码中的每个缺陷都应该是   尽可能致死   可能的。

通过这种方式,可以找到并修复错误,并且软件变得越来越强大。别人说的是对的;永远不会发现你不期望的例外,并知道如何处理。