.NET 中的 SerialPort 是非托管资源吗?我的包裹类正确吗?

发布于 2024-10-14 21:14:15 字数 2681 浏览 3 评论 0原文

我在串行端口类上有适配器模式(包装器)。我应该实现 IDisposable 模式并在其中调用 _wrappedSerialPort.Dispose() 吗?有我的班级,对吗?

public class SerialPortAdapter : ISerialPortAdapter
{
    private bool _disposed;

    public event SerialDataReceivedEventHandler DataReceived;

    private readonly SerialPort _wrappedSerialPort;

    public SerialPort WrappedSerialPort
    {
        get { return _wrappedSerialPort; }
    }

    public string PortName
    {
        get { return _wrappedSerialPort.PortName; }
        set { _wrappedSerialPort.PortName = value; }
    }

    public BaudRate BaudRate
    {
        get { return (BaudRate)Enum.ToObject(typeof(BaudRate), _wrappedSerialPort.BaudRate); }
        set { _wrappedSerialPort.BaudRate = (int)value; }
    }

    public bool IsOpen
    {
        get { return WrappedSerialPort.IsOpen; }
    }

    public SerialPortAdapter(SerialPort serialPort)
    {
        _wrappedSerialPort = serialPort;
        _wrappedSerialPort.DataReceived += SerialPortDataReceived;
    }

    public void OpenPort()
    {
        if (!_disposed)
        {
            if (!WrappedSerialPort.IsOpen)
            {

                WrappedSerialPort.Open();

            }
        }
    }


    public void ClosePort()
    {
        if (!_disposed)
        {
            if (WrappedSerialPort.IsOpen)
            {

                WrappedSerialPort.Close();

            }
        }
    }


    public void WriteLine(string request)
    {
    ...
    }


    public void Write(byte[] request)
    {
       ....
    }


    public byte[] Read()
    {
      ....
    }


    public string ReadLine()
    {
       ...
    }


    private void SerialPortDataReceived(object sender, SerialDataReceivedEventArgs e)
    {
        if (DataReceived != null)
        {
            DataReceived(this, e);
        }
    }

    #region IDisposable Members

    public virtual void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    private void Dispose(bool disposing)
    {
        if (!_disposed)
        {
            if (disposing)
            {
                // Dispose managed resources.

            }
            // Dispose unmanaged resources.

            ClosePort();
            WrappedSerialPort.DataReceived -= SerialPortDataReceived;
            _wrappedSerialPort.Dispose();

            _disposed = true;

        }
    }

    ~SerialPortAdapter()
    {

        Dispose(false);
    }

    #endregion
}

编辑:是否有必要调用此函数,或者仅调用 _wrappedSerialPort.Dispose(); 就足够了?

        ClosePort();
        WrappedSerialPort.DataReceived -= SerialPortDataReceived;
        _wrappedSerialPort.Dispose();

I have adapter pattern (wrapper) over serial port class. Should I implement IDisposable pattern and call _wrappedSerialPort.Dispose() in it? There is my class, is it correct?

public class SerialPortAdapter : ISerialPortAdapter
{
    private bool _disposed;

    public event SerialDataReceivedEventHandler DataReceived;

    private readonly SerialPort _wrappedSerialPort;

    public SerialPort WrappedSerialPort
    {
        get { return _wrappedSerialPort; }
    }

    public string PortName
    {
        get { return _wrappedSerialPort.PortName; }
        set { _wrappedSerialPort.PortName = value; }
    }

    public BaudRate BaudRate
    {
        get { return (BaudRate)Enum.ToObject(typeof(BaudRate), _wrappedSerialPort.BaudRate); }
        set { _wrappedSerialPort.BaudRate = (int)value; }
    }

    public bool IsOpen
    {
        get { return WrappedSerialPort.IsOpen; }
    }

    public SerialPortAdapter(SerialPort serialPort)
    {
        _wrappedSerialPort = serialPort;
        _wrappedSerialPort.DataReceived += SerialPortDataReceived;
    }

    public void OpenPort()
    {
        if (!_disposed)
        {
            if (!WrappedSerialPort.IsOpen)
            {

                WrappedSerialPort.Open();

            }
        }
    }


    public void ClosePort()
    {
        if (!_disposed)
        {
            if (WrappedSerialPort.IsOpen)
            {

                WrappedSerialPort.Close();

            }
        }
    }


    public void WriteLine(string request)
    {
    ...
    }


    public void Write(byte[] request)
    {
       ....
    }


    public byte[] Read()
    {
      ....
    }


    public string ReadLine()
    {
       ...
    }


    private void SerialPortDataReceived(object sender, SerialDataReceivedEventArgs e)
    {
        if (DataReceived != null)
        {
            DataReceived(this, e);
        }
    }

    #region IDisposable Members

    public virtual void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    private void Dispose(bool disposing)
    {
        if (!_disposed)
        {
            if (disposing)
            {
                // Dispose managed resources.

            }
            // Dispose unmanaged resources.

            ClosePort();
            WrappedSerialPort.DataReceived -= SerialPortDataReceived;
            _wrappedSerialPort.Dispose();

            _disposed = true;

        }
    }

    ~SerialPortAdapter()
    {

        Dispose(false);
    }

    #endregion
}

Edit: Is it necessary to call this, or is enough to call only _wrappedSerialPort.Dispose();?

        ClosePort();
        WrappedSerialPort.DataReceived -= SerialPortDataReceived;
        _wrappedSerialPort.Dispose();

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

手心的温暖 2024-10-21 21:14:15

Henk Holterman 的答案是正确的:SerialPort 是一个托管资源,它本身拥有一个非托管资源,因此实现了 IDisposable

由于您的包装器拥有 SerialPort,因此它间接拥有 SerialPort 的非托管资源,因此必须实现 IDisposable。您的实现是错误的,只有在 diswriting 为 true 时才应处置拥有的 SerialPort 实例,因为它是托管资源。

它应该按如下方式实现:

   private void Dispose(bool disposing)
    {
        if (!_disposed)
        {
            if (disposing)
            {
                // Dispose managed resources.
                ClosePort();
                WrappedSerialPort.DataReceived -= SerialPortDataReceived;
                _wrappedSerialPort.Dispose();
            }
            _disposed = true;
        }
    }

此外,正如 Henk Holterman 指出的那样,如果您直接拥有非托管资源,则只需要一个析构函数,但这里的情况并非如此,并且您可以通过获取来简化 IDisposable 实现摆脱析构函数。

Henk Holterman's answer is correct: SerialPort is a managed resource, which itself owns an unmanaged resource and hence implements IDisposable.

Since your wrapper owns a SerialPort, it indirectly owns SerialPort's unmanaged resource and hence must implement IDisposable. Your implementation is wrong, the owned SerialPort instance should only be disposed if disposing is true, since it is a managed resource.

It should be implemented as follows:

   private void Dispose(bool disposing)
    {
        if (!_disposed)
        {
            if (disposing)
            {
                // Dispose managed resources.
                ClosePort();
                WrappedSerialPort.DataReceived -= SerialPortDataReceived;
                _wrappedSerialPort.Dispose();
            }
            _disposed = true;
        }
    }

Also, as Henk Holterman points out, you only need a destructor if you directly own unmanaged resources, which is not the case here, and you can simplify the IDisposable implementation by getting rid of the destructor.

萌能量女王 2024-10-21 21:14:15

SerialPort 本身是非托管资源的所有者,这就是它实现完整一次性模式的原因。

在您的类中,_wrappedSerialPort 是一个托管资源。我的定义:托管资源是间接非托管资源

您的班级不需要需要完整的模式。您可以而且应该省略析构函数(或终结器),~SerialPortAdapter (),然后您可以跳过 SupressFinalize。

最好保留其余部分,但您会发现很容易进一步缩短代码(因为 void Dispose(bool) 永远不会用 false 调用>)。

The SerialPort itself is the owner of an unmanaged resource and that is why it implements the full Disposable pattern.

In your class, the _wrappedSerialPort is a managed resource. My definition: a managed resource is an indirect unmanaged resource.

Your class does not need the full pattern. You could and should omit the destructor (or finalizer), ~SerialPortAdapter () and following that you can skip the SupressFinalize.

It would be best to leave the rest, but you will see it would be easy to shorten the code a lot more (because void Dispose(bool) will never be called with false).

只是在用心讲痛 2024-10-21 21:14:15

是的,在这种情况下,您实现 Dispose 方法是正确的。确保将 IDisposable 添加到您的类声明中。这使得可以使用非常方便的 using 构造,如下所示:

using (var port = new SerialPortAdapter(serialPort)) {
    port.OpenPort();
    // use port
}

在包装的串行端口上调用 Dispose 应该足够了,因为这将关闭端口。根据 MS 文档,Close 将在内部调用 Dispose。不过,通过显式调用 Close 来明确您的意图并没有什么坏处。

像您一样,从活动中取消注册是一个很好的做法。

http://msdn.microsoft.com/en -us/library/system.io.ports.serialport.close.aspx

Yes, you are correct in implementing a Dispose method in this case. Make sure to add IDisposable to your class declaration. This makes it possible to use the very handy using construct, like this:

using (var port = new SerialPortAdapter(serialPort)) {
    port.OpenPort();
    // use port
}

Calling Dispose on the wrapped serial port ought to be enough, since this will close the port. According to MS documentation, Close will call Dispose internally. No harm in being clear in your intentions by explicitly calling Close, though.

Unregistering from the event, like you are doing, is good practice.

http://msdn.microsoft.com/en-us/library/system.io.ports.serialport.close.aspx

绝影如岚 2024-10-21 21:14:15
  • 是的,串行罐是一个非托管报告。或者您是否见过物理硬件的垃圾收集器? ;)

  • 这由实现 IDisposable 的访问类显示 - 这意味着您托管长期引用的类也必须实现 IDISPOSABLE。

  • Yes, the serial pot is an unmanaged report. Or did you ever see a garbage collector for the PHYSICAL HARDWARE? ;)

  • This is shown by the class for access implementing IDisposable - which means your class hosting a lon term refernce pertty much HAS TO IMPLEMENT IDISPOSABLE, TOO.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文