0

I am using a .net SerialPort as property in a class for communication with some hardware. If I close the program I need to send a stop command before I close the connection.

I thought that the most elegant way would be to do this in my decontructor of the class I wrote but I had to find out that my SerialPort is closed at the time the decontrcutor is fired and cannot be opend again.

Here is a test class I wrote which produces the same error:

public class SerialPortTestClass
{
    private System.IO.Ports.SerialPort ComPort { get; set; }

    public SerialPortTestClass()
    {
        ComPort = new System.IO.Ports.SerialPort
        {
            BaudRate = 38400,
            StopBits = System.IO.Ports.StopBits.One,
            NewLine = ((char)19).ToString(),
            Parity = System.IO.Ports.Parity.None,
            Handshake = System.IO.Ports.Handshake.None,
            RtsEnable = false,
            ReadBufferSize = 512,
            ReadTimeout = 5000,
            ReceivedBytesThreshold = 1
        };
    }

    public void Connect(string port)
    {
        ComPort.PortName = port;
        ComPort.Open();
    }

    public void Disconnect()
    {
        var bytes = new byte[] { 83, 80, 32, 115, 54, 19 };
        ComPort.Write(bytes, 0, bytes.Length);
        ComPort.Close();
    }

    ~SerialPortTestClass()
    {
        if (ComPort.IsOpen)
            Disconnect();
    }
}

Has anybody an idea why the SerialPort is closed and how to fix this behavior?

dukemadcat
  • 23
  • 1
  • 5
  • This has nothing to do with the serial port. It's because the destructor isn't called on shutdown. To solve that one need to know how you run the class. A console application? Web application? – fhogberg May 10 '17 at 22:39
  • The class is part of a wpf desktop application. – dukemadcat May 12 '17 at 06:18

1 Answers1

1

The problem with this is you need to make sure the code run when the application exits. Destructors are not guaranteed to run on app exit.

One method is to make your class IDisposable. Wrap your instance in a using block and you will be sure that Dispose() is called before exit.

public class SerialPortTestClass : IDisposable
{
    public void Dispose()
    {
        if (ComPort.IsOpen)
            Disconnect();
    }
    ...

and usage:

using (var sp = new SerialPortTestClass())
{
    //Your code goes here
}

If the SerialPortTestClass lives in a window then you should call the disconnect when the window closes. I beleive this always happend on app exit. For a WPF application that would be adding the following method to your MainWindow.xaml.cs

protected override void OnClosed(EventArgs e)
{
    var vm = this.DataContext as MainWindowViewModel;
    vm.SerialPort.Disconnect();
    base.OnClosed(e);
}
fhogberg
  • 415
  • 3
  • 11
  • The class using the `SerialPort` runs over the complete run time of the program so writing a local `using` statement would be difficult. – dukemadcat May 12 '17 at 08:51
  • where do you create the SerialPortTestClass and how do you reference it? – fhogberg May 12 '17 at 11:06
  • It is declared and initialized in my `ViewModel` which is which is referenced like: – dukemadcat May 12 '17 at 11:43
  • Thanks @fhogberg. That looks like my current workaround ;) But I will need to use the class in some projects and I thought it would be nicer if the class can do this part on its own so that I cannot forget to do it. Also I was curious if anybody could explain me this strange behavior. – dukemadcat May 12 '17 at 12:24
  • For an explanation see http://stackoverflow.com/a/6931350/2429139 A destructor handles freeing memory. Your assumption that the destructor is called when the application exits is just wrong. – fhogberg May 12 '17 at 20:26
  • I did not really expect the destructor to be called exactly when the window is closing but as part of closing the application I expected the destructor to be called when the class gets "destroyed" which actually happens. And because the SerialPort is part of the class I did not expect it to be closed at this point which seems not to be true. – dukemadcat May 13 '17 at 22:47