【问题标题】:Pattern for managing reference count and object life管理引用计数和对象寿命的模式
【发布时间】:2011-01-28 21:36:31
【问题描述】:

我们有一个串行端口,它通过同一条线路连接到数百个物理设备。我们有 Modbus 和 Hart 等协议来处理应用程序和设备之间的请求和响应。该问题与管理通道的引用计数有关。当没有设备正在使用该通道时,应关闭该通道。

public class SerialPortChannel
{ 
   int refCount = 0;
   public void AddReference()
   {
      refCount++;
   }   


   public void ReleaseReference()
   {
      refCount--;
      if (refCount <= 0)
           this.ReleasePort(); //This close the serial port
   }   

}

对于每个连接的设备,我们为设备创建一个对象,例如

  device = new Device();
  device.Attach(channel);    //this calls channel.AddReference()

当设备断开连接时,

  device.Detach(channel); //this calls channel.ReleaseReference()

我不相信引用计数模型。在 .NET World 中有没有更好的方法来处理这个问题?

【问题讨论】:

  • ReleasePort 方法有什么作用?
  • @ReleasePort 关闭底层端口,然后串口对象不再可用
  • 有了所有滥用单例的方法,这是一个很好的地方。第一次访问会打开它,并在应用程序关闭时关闭。

标签: c# .net vb.net design-patterns oop


【解决方案1】:

您可以考虑让Attach 返回实现IDisposable 的类型。这将公开可用的端口成员,但它们会在内部委托回原始对象(不会公开公开Attach以外的任何内容);调用Attach 会增加引用计数;处理返回的值会减少它。然后你就可以做到:

using (Foo foo = device.Attach(channel))
{
    ...
}

要记住的一个奇怪之处是,您从引用计数 0 开始 - 但没有关闭端口。您是否应该只在第一次调用Attach 时打开它?

【讨论】:

  • @Jon,感谢您的回答。使用块作用域以毫秒间隔访问实时设备是否有意义?对垃圾收集器来说不是负担吗?
  • @Gopalakrishnan:GC 可以在一毫秒内收集大量的对象 :) 你打算多久附加到设备上?我本来期望连接到设备的正常用例,执行相当大的工作然后分离。如果您希望每秒附加数百万次,那么它可能导致 GC 问题 - 但重要的是要知道 .NET 不是实时的平台入手。如果您的应用无法应对偶尔的短暂停顿,您很可能会遇到问题。
  • ".NET 并不是一个实时平台。"我经常听到这种说法,但对于“为什么不”这个问题,我很难得到更准确的答案。您认为什么是实时?为什么 .net 不是实时框架/平台?
  • @derSteve:如en.wikipedia.org/wiki/Real-time_computing - 响应时间等方面存在硬性限制。您需要在实时操作系统上运行才能开始,我怀疑垃圾收集的不确定性至少需要进行重大更改....
【解决方案2】:

正如 Jon Skeet 的回答中提到的,您应该使用 Disposable 模式,但是,由于您似乎在并行环境中使用此类,因此您的增量 (++) 和减量 (--) 需要是原子的,使用Interlocked.Increment.Decrement

事实上,您可能需要一个对象来打开lock(),这样您就可以在计数为1 时增加和打开设备(同时第二个Attach 可以尝试再次打开设备)并减少然后当计数为0时关闭设备。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多