【问题标题】:TcpClient field of abstract base class constantly being disposed抽象基类的 TcpClient 字段不断被释放
【发布时间】:2008-10-15 08:33:01
【问题描述】:

我有一个带有 TcpClient 字段的抽象基类:

public abstract class ControllerBase
{
    internal protected TcpClient tcpClient;

它有一个建立连接的方法:

private void setupConnection(IPAddress EthernetAddress, ushort TcpPort)
    {
        if (this.tcpClient == null || !this.tcpClient.Connected)
        {
            this.tcpClient = new TcpClient();

            try
            {
                this.tcpClient.Connect(EthernetAddress, TcpPort);
            }
            catch(Exception ex)
            {
                throw new TimeoutException("The device did not respond.\n" + ex.Message);
            }
        }
    }

比请求数据的方法:

 internal protected virtual byte[] requestData(IPAddress EthernetAddress, ushort TcpPort, byte[] data, bool IgnoreResponse)
    {
        setupConnection(EthernetAddress, TcpPort);

        //The rest of the code uses this.tcpClient 

还有一些其他的,例如 requestRawData 等...它们是非常特定的硬件通信协议所必需的,但这绝不是这个问题的一部分。

然后我有从这个类派生的类,它们覆盖了基类方法:

public class Controller : ControllerBase
{
  internal virtual byte[] requestData(byte[] data, bool IgnoreResponse)
  {
        return base.requestData(this.eth0.EthernetAddress, this.eth0.TcpPort, data, IgnoreResponse);
  }

代码正常工作,没有任何异常,但是每次调用 setupConnection 方法时, TcpClient 实例(tcpClient)好像被释放了,所以创建了一个新的实例并再次调用了connect方法,确实减慢了通信过程。

注意:子类的公共方法调用requestData方法, 使用此库从开发人员那里抽象出许多细节。

如SetDevicePower(byte PowerLevel)、QueryDeviceName()等...

这样的代码:

Controller controller = new Controller("172.17.0.3",34000);
string name = controller.QueryDeviceName();
controller.SetDevicePower(200);

导致 connect 方法被调用两次......为什么它在调用之间被释放?

【问题讨论】:

    标签: c# .net dispose tcpclient


    【解决方案1】:

    您可能想研究一下“setupConnection”方法中的一些低效问题。第一个问题是您在 TcpClient 关闭时对其进行实例化。这不是必需的。我会将空检查和连接逻辑拆分为 2 个方法,或者方法中至少有两个代码块:

      if (this.tcpClient == null)
      {
        this.tcpClient = new TcpClient();
      }
    
      try
      {
        if (!this.tcpClient.Connected)
        {
          this.tcpClient.Connect(EthernetAddress, TcpPort);
        }
      }
      catch(Exception ex)
      {
        throw new TimeoutException("The device did not respond.\n" + ex.Message);
      }
    

    其次,catch(Exception) 也是一个坏主意,您不能假设异常是超时,因为这里应该捕获许多其他异常。

    至于您的答案:您可能必须在您的 requestData 方法中提供进一步的实现细节,因为那里可能有线索。例如,您要关闭连接吗?如果是这样,您最终会在下次调用 setupConnection 时创建一个新的 TcpClient 对象,这可能就是这里发生的情况。

    希望这能有所启发。

    【讨论】:

      猜你喜欢
      • 2016-09-11
      • 2011-09-25
      • 2019-11-03
      • 2011-08-05
      • 2019-12-26
      • 2018-07-11
      • 1970-01-01
      • 2011-06-18
      • 1970-01-01
      相关资源
      最近更新 更多