【问题标题】:What is the drawback if I do not invoke the UdpClient.Close() method?如果我不调用 UdpClient.Close() 方法有什么缺点?
【发布时间】:2012-10-08 06:44:26
【问题描述】:

我有以下代码块,它影响了我的程序效率。这里的问题是,如果目标主机存在,一切正常。但如果它确实存在,执行起来需要很长时间。最后,我发现“udp.Close()”占据了大部分的执行时间。如果我不调用close方法,效率还是不错的。

如果我不调用 close 方法,谁能帮我告诉我有什么缺点?非常感谢。

{ // This is my code block, I need to execute it many many times.
string ipAddress = Dns.GetHostAddresses("joe-pc").FirstOrDefault().ToString();
UdpClient udp = new UdpClient(ipAddress, Port);
udp.Send(msg, msg.Length);
udp.Close();
udp = null;
}

【问题讨论】:

  • 旁注 - 为什么之后将其设置为 null
  • 根据我的个人经验,需要设置udp = null;在 udp.Close() 之后的最后。我使用内存分析器(dotmemory)检查了保留的实例,发现 UdpClient 实例仍然存在,除非 udp = null;被使用。

标签: c# .net udpclient


【解决方案1】:

缺点是你会有资源泄漏。你可能很幸运,垃圾收集经常发生,以至于它没有在你的程序中展示自己,但为什么要冒险呢?来自Close的文档:

关闭会禁用底层Socket并释放与UdpClient关联的所有托管和非托管资源。

注意,它涉及非托管资源。这些将由运行一些代码的UdpClient 发布 - 它要么在 Close/Dispose 中执行,要么必须在其 Finalize 方法中执行 - 没有其他的导致它们被释放(假设程序保持运行)。

也许可以隐藏Close 操作的成本,方法是使用Task.Run 让它在另一个线程上运行 - 但您必须权衡这样做的成本.


或者,更具体的说——你说你需要这个方法运行很多次。如果不在这里清理您的资源,您将增加后续调用完全失败的机会,因为它无法获取所需的资源(它们都被绑定在现有的、非Closed UdpClient 个实例)。


而且,正如我的评论中所指出的,以下行毫无意义:

udp = null;

此类代码曾经在 COM 时代的 VB 中使用,但它在 .NET 世界中没有位置。

【讨论】:

    【解决方案2】:

    Close() 禁用底层 Socket 并释放与 UdpClient 关联的所有托管和非托管资源。 如果你没有关闭,那么它不会禁用和释放资源,比如你的端口和 IP 地址

    【讨论】:

      【解决方案3】:

      您是否可以使用BeginSend 而不是使用Send,然后在您尝试关闭时在回调中处理异常(如果这确实是问题)?

      【讨论】:

        【解决方案4】:

        随着 dns 记录的更改,您可能使用不同的 ip 地址来定位 joe-pc,但您为每次发送重复使用相同的 UdpClient。完成后记得关闭()它。

        使用

        //
        // Summary:
        //     Sends a UDP datagram to a specified port on a specified remote host.
        //
        // Parameters:
        //   dgram:
        //     An array of type System.Byte that specifies the UDP datagram that you intend
        //     to send represented as an array of bytes.
        //
        //   bytes:
        //     The number of bytes in the datagram.
        //
        //   hostname:
        //     The name of the remote host to which you intend to send the datagram.
        //
        //   port:
        //     The remote port number with which you intend to communicate.
        //
        // Returns:
        //     The number of bytes sent.
        //
        public int Send(byte[] dgram, int bytes, string hostname, int port);
        

        并跳过 dns 查找。

        【讨论】:

          【解决方案5】:

          我知道这是一段时间,但我今天偶然发现了这个问题并想补充:

          udp=null;

          恕我直言,这不是毫无意义的。在某些情况下,您可以在内存分析器中看到,如果您不将其设置为 null,您的实例仍然可用。

          【讨论】:

          • 我也注意到了。 udp.Close() 没有从堆中删除实例。需要添加udp=null;在 udp.Close() 之后删除实例。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-03-08
          • 1970-01-01
          • 1970-01-01
          • 2012-07-25
          • 2016-05-23
          • 2019-11-09
          相关资源
          最近更新 更多