【问题标题】:How to supress the creation of an (.net) Exception object?如何禁止创建(.net)异常对象?
【发布时间】:2009-05-22 10:17:15
【问题描述】:

如果我不关心抛出的异常。我可以以不创建它的方式编码吗?

也就是说,可以抛出异常但不创建异常对象吗?

一个示例 - 使用 System.Net.Sockets.Socket 的简单示例

 Socket acceptingSocket;
acceptingSocket.Blocking = false;

while(condition)
{
    try
    {
        Socket acceptedSocket = acceptingSocket.Accept(); //(i)
        doWork(acceptedSocket);
    }
    catch{}
}

因为套接字处于非阻塞模式 如果没有连接接受 在点 (i) 抛出 SocketException 条件循环继续。

使用此代码实现 - 会创建 SocketException 对象吗?

如果它被创建了 - 有没有办法不创建它?

【问题讨论】:

    标签: c# .net exception memory garbage-collection


    【解决方案1】:

    是的,它将被创建。 不,没有办法避免这种情况。

    【讨论】:

      【解决方案2】:

      你不能抑制异常,你只能忽略它们。在任何情况下,昂贵的不是创建 Exception 对象——而是抛出异常时发生的堆栈遍历。

      还有,

      catch(SocketException) {}
      

      不是

      catch { } or catch(Exception) { }
      

      :)

      【讨论】:

        【解决方案3】:

        它将始终被创建。 AFAIK 无法阻止创建异常对象...

        【讨论】:

          【解决方案4】:

          抛出异常时总是会创建一个异常对象。您所做的只是指定您不关心异常是什么类型并且您不需要引用它。如果acceptingSocket.Accept 抛出异常,doWork 将不会被调用。

          您的代码相当于:

          catch(Exception) {}
          

          【讨论】:

          • 我不这么认为——一个裸catch语句会捕获一些本地代码抛出的非CLR异常,而catch(Exception)只会捕获CLR异常。
          • 好点,虽然我的主要观点是不能阻止异常对象的创建。
          【解决方案5】:

          我认为这无关紧要但很重要。

          为什么您的套接字在循环内处于非阻塞模式?如果套接字没有传入连接,您只需无限期地再次进入循环,直到有这样的连接。你在这里做的是busy waiting,它会占用大量的 CPU 资源 - 在这里创建的异常真的不应该让你担心。

          【讨论】:

          • @configurator - 我希望能够轻松停止/启动/停止接受连接。如果线程在等待 Accept() 时被阻塞,这是不可能的。我的代码在调用 Accept() 之前确实使用了 Socket.Poll() 和其他方法,以免抛出 SocketExceptions。但是,您是对的,它是“忙于等待”。我假设如果我使用阻塞套接字是正确的 - 套接字只会“忙于等待”较低级别的连接?
          • 不,你错了。套接字不会忙于等待,而是实际上在等待。这意味着线程不会占用 cpu 并且不会被分配时间,直到底层信号量(或互斥体或其他)被释放。您可以通过其他方式断开线程。也许如果你添加一个超时时间,比如 500 毫秒,它只会每秒重新启动两次等待,并且可以很快停止。
          • @configurator - 感谢您的超时建议,它将实施:)
          【解决方案6】:

          已经指出你无法阻止它,但我想指出原因。您调用的代码可能在您的代码之前编写。并且在编写时,已经确定了引发异常的情况。您在代码中所做的任何事情都无法及时返回并更改被调用者的开发人员所做的决定。

          请注意,智能虚拟机可能能够在 JITting 时消除异常。与您和其他开发人员不同的是,它看到了双方的结合,并且可以根据结合做出明智的决策。 x86 异常模型无论如何都与 .Net 异常模型不匹配,因此 VM 已经必须执行智能映射。例如。在这种情况下,它可能会通过返回一个空指针来逃脱 - 您的代码不会注意到。

          【讨论】:

            【解决方案7】:

            除非您的代码或环境真的搞砸了,否则不要担心偶尔出现异常的性能成本。异常总是在运行时发生,这没什么大不了的。当然,如果你最终做了一些疯狂的事情,比如走过数组的末尾,这样你就可以跳过对数组长度的测试,如果你的方法被频繁调用,那将会受到伤害。

            尽量避免不必要地投掷/造成它们。

            【讨论】:

              【解决方案8】:

              如前所述,如果一个异常被捕获并被忽略,那么它就会被创建并抛出。当异常情况已经发生时,无法抑制异常的创建和抛出,但是,您通常可以采取一些措施来防止异常情况发生。

              在您的情况下,您使用的是 Socket。可能引发 SocketException 的原因有很多……例如尝试从关闭的套接字中读取。为了防止抛出异常,您需要在启动读取之前验证套接字是否仍然打开。这将导致在每次读取之前检查套接字状态的额外成本,但从长远来看,您可能会在达到从关闭的套接字读取并引发异常所产生的开销水平之前执行数千次此类检查。

              一般来说,执行此类检查只是一种良好的编程习惯。我们应该编写尽可能避免异常情况的代码。一个典型的例子是在访问参数和其他变量的方法或属性之前检查参数和其他变量是否为 null,这样可以避免可怕的 NullReferenceException(在正确编写的应用程序中,永远不应该抛出的异常。)

              要始终注意代码中可能出现的异常情况需要一点时间和经验,但是如果您尝试静下心来考虑它,那么在大多数情况下,您可以通过以下方式避免异常情况在以会导致异常的方式使用之前验证您的输入、接收到的数据等。

              【讨论】:

              • @jrista - 感谢您的建议和指导 - 我正在学习 c# - 这个周末我将研究测试 - 如果我想测试你的陈述

                “这将导致在每次读取之前检查套接字状态的额外成本,但从长远来看,您可能会执行数千次这样的检查,然后才能达到从关闭的套接字读取并抛出一个会发生异常。”

                我该怎么办?
              猜你喜欢
              • 2022-07-04
              • 2017-12-04
              • 1970-01-01
              • 2012-03-09
              • 2011-05-01
              • 2019-12-13
              • 2014-05-07
              • 1970-01-01
              • 2014-01-24
              相关资源
              最近更新 更多