C#中的事件处理程序是否应该引发异常?

C#中的事件处理程序是否应该引发异常?,c#,events,exception,C#,Events,Exception,作为一般规则,在任何情况下,负责侦听事件的方法是否可以抛出引发事件的类必须处理的异常(或允许抛出异常) 考虑到这种异常会阻止该事件的其他侦听器随后被调用,允许这种情况发生似乎有点“反社会”,但另一方面,如果存在异常,它应该怎么办?在理想情况下,事件处理程序不应该引发异常。在事件处理程序中引发异常往往会导致非常难以处理的情况和意外行为。正如您所提到的-这会阻止后续事件处理程序查看事件,并且异常会传播到事件生成器的代码中,因为它引发了事件 理想情况下,事件处理程序应该是快速的(如果它们运行时间长,他

作为一般规则,在任何情况下,负责侦听事件的方法是否可以抛出引发事件的类必须处理的异常(或允许抛出异常)


考虑到这种异常会阻止该事件的其他侦听器随后被调用,允许这种情况发生似乎有点“反社会”,但另一方面,如果存在异常,它应该怎么办?

在理想情况下,事件处理程序不应该引发异常。在事件处理程序中引发异常往往会导致非常难以处理的情况和意外行为。正如您所提到的-这会阻止后续事件处理程序查看事件,并且异常会传播到事件生成器的代码中,因为它引发了事件


理想情况下,事件处理程序应该是快速的(如果它们运行时间长,他们应该尝试将工作安排在单独的线程中),尽可能地接近错误。

< P>从事件处理程序中抛出异常与从代码< IDISPOLIDLE抛出异常类似。Debug“< /C>方法”(或C++析构函数)。这样做会给打电话的人带来很大的麻烦,因为你让他们别无选择


  • 忽略异常并让它传播。这打破了他们通知所有听众事件的约定。如果堆栈中高于它们的任何人捕捉到异常,这将是一个非常现实的问题
  • 捕捉它,调用其他处理程序并重试。但是如果其他人中的一个也扔了会怎么样呢
  • 接受例外。总的来说,这很糟糕。事件源应该不知道它们的调用者,因此不知道它们在吞咽什么
  • 因为你已经被烤熟了,所以进程崩溃了 在所有这些中,4个是最好的选择。但这是很少做到的,不能指望

    我认为在您的组件中,您实际上只有几个选项

    • 您正在调用正在抛出的代码,该代码处于处理异常的最佳位置。如果你无法处理,那么指望别人来处理是不合理的。因此,请崩溃该过程并完成它
    • 不要调用抛出

      • 理想的说法是,不应该存在例外情况。在一个开发人员的真实世界中,异常总是被期望的,并且应该在情况要求时被拦截(捕获)、传播或禁止

        所以

        有没有什么情况 这对于一种方法来说是可以接受的 负责听一个事件 抛出异常

        对。您可以预期每个方法都会出现异常,不管是否对事件负责

        要捕获Windows应用程序中的几乎所有异常,请使用:


        事件中仅有的两种类型的异常是严重的,可能导致进程结束的异常,如
        System.OutOfMemoryException
        System.DllNotFoundException
        ,以及明显的编程错误,类似于
        System.StackOverflowException
        System.InvalidCastException
        。捕获和删除这些类型的异常从来都不是一个好主意——让它们浮到顶部,让开发人员决定在应用程序级别如何处理它们


        至于其余的。。。任何常见或常见的异常,如
        System.IO.IOException
        ,都应该在事件内部处理,并且应该有一些机制将此类错误条件返回给调用方

        这里的一些答案表明,从事件处理程序中抛出是不好的(“对调用方造成严重破坏”,“往往导致非常难以处理的情况,以及意外的行为”…)

        我觉得这是胡说八道

        general情况下,完全可以从事件处理程序中抛出。当然,其他事件处理程序不会运行-抛出的事件处理程序也不会运行到底,在事件触发和捕获点之间的任何其他代码也不会运行。那又怎么样?抛出异常时不执行代码是完全正常的-如果需要保证它的执行,那么使用finally块

        当然,在任何<>强>特定< /强>的情况下,您可能想考虑哪一个,如果有的话,它是适当的例外处理,就像您将与任何其他代码一样。 一如往常,没有适用于所有情况的硬性规定。这里的一个答案是“事件处理程序应该很快…并且接近无错误…”。一个反例是ASP.NET Page.Load事件

        NET中的一条一般规则是,吞并所有异常几乎总是一个坏主意:这适用于事件处理程序,就像它适用于任何其他代码一样

        因此,对于原始问题“在任何情况下,负责监听事件的方法抛出异常是否可以接受”的答案肯定是


        正如对“在任何情况下,负责侦听事件的方法是否可以接受吞咽异常”这一问题的回答也是肯定的。

        还有CancelEventArgs。我不明白你在这里的意思。你的意思是说,在say Button1_Click的接收端,你想抛出一个异常?@Rob:假设你有一个长时间运行的流程,并且有一个已完成的事件。10个方法与此注册。如果其中一个抛出异常,其余的将不会被调用。
        要抛出异常的事件处理程序
        ?可能委托可以引发异常,但处理程序。。?!有效点;我已经澄清了一点,指的是“负责监听事件的方法”,而不是“事件处理程序”。哦,这让我想到了。。
        ThreadAbortException
        怎么样?
        ThreadAbortException
        是一个有趣的问题,因为不管你是否捕捉到它,它都会被忽略