C# .NET中的SerialPort是非托管资源吗?我的课程对吗?

C# .NET中的SerialPort是非托管资源吗?我的课程对吗?,c#,.net,serial-port,C#,.net,Serial Port,我在串口类上有适配器模式(包装器)。我应该实现IDisposable模式并在其中调用_wrappedSerialPort.Dispose()?这是我的班级,对吗 public class SerialPortAdapter : ISerialPortAdapter { private bool _disposed; public event SerialDataReceivedEventHandler DataReceived; private readonly Se

我在串口类上有适配器模式(包装器)。我应该实现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()

  • 是的,串行pot是非托管报告。或者你见过物理硬件的垃圾收集器吗?;)

  • 实现IDisposable的access类显示了这一点,这意味着承载长期引用的类也必须实现IDisposable


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

using (var port = new SerialPortAdapter(serialPort)) {
    port.OpenPort();
    // use port
}
在包装好的串行端口上调用Dispose应该足够了,因为这将关闭端口。根据MS文档,
Close
将在内部调用
Dispose
。不过,明确地调用
Close
,明确自己的意图并没有坏处

与您现在所做的一样,从活动中注销是一种良好的做法


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

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

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


最好留下剩下的代码,但您会发现代码很容易缩短很多(因为
void Dispose(bool)
永远不会用
false
调用)。Henk Holterman的答案是正确的:SerialPort是一个托管资源,它本身拥有一个非托管资源,因此实现了
IDisposable

由于包装器拥有SerialPort,因此它间接拥有SerialPort的非托管资源,因此必须实现IDisposable。您的实现是错误的,只有当
disposing
为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实现。

我想知道是否应该调用close,然后取消注册事件,然后在dispose方法中进行dispose。应该足够只调用dispose吗?事件如何?串行端口是非托管资源,但SerialPort类是托管资源。
   private void Dispose(bool disposing)
    {
        if (!_disposed)
        {
            if (disposing)
            {
                // Dispose managed resources.
                ClosePort();
                WrappedSerialPort.DataReceived -= SerialPortDataReceived;
                _wrappedSerialPort.Dispose();
            }
            _disposed = true;
        }
    }