views:

1146

answers:

6

The computer is connected to measuring device via a physical COM1. I have simple form where I open a serial port, tell the device that I'm alive and occasionally the device sends data. (every some minutes)

Thread _readThread = new Thread(Read);
SerialPort _serialPort = new SerialPort("COM1", 9600);
_serialPort.Parity = Parity.None;
_serialPort.DataBits = 8;
_serialPort.StopBits = StopBits.One;
_serialPort.Handshake = Handshake.None;
_serialPort.DtrEnable = true;
_serialPort.Open();
_readThread.Start();
_serialPort.Write("#listening");

The read function (which works):

public void Read()
{
    string message = _serialPort.ReadLine();
}

After approximately one minute the application crashes (even while debugging). It reports an ObjectDisposedException (for the underlying stream?). The message tells that the SafeHandle was closed. Stack strace is below:

at Microsoft.Win32.UnsafeNativeMethods.GetOverlappedResult(SafeFileHandle hFile, NativeOverlapped lpOverlapped, Int32& lpNumberOfBytesTransferred, Boolean bWait) at System.IO.Ports.SerialStream.EventLoopRunner.WaitForCommEvent() at System.Threading.ThreadHelper.ThreadStart_Context(Object state) at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state) at System.Threading.ThreadHelper.ThreadStart()*

Any ideas? The problem is reported widely but usually involve the device beeing physically detached from the PC.

A: 

ObjectDisposedException means someone called Dispose on the object. What are you doing after you start the read thread? Do you wait for the read thread to complete before you exit the program? Otherwise, maybe the read thread is still running with the program exits.

John Saunders
I don't exit the program it just runs an then suddenly crashes. I really do nothing after that, and it does not crash on receive. If I ended the app myself I would correctly close COM1 and dispose buffers.
Stefan Teitge
A: 

I had something similiar happen to me about a year ago. For some reason, some characters at the end of the read buffer would cause the C# interface to the serial port to close itself. It usually happened when \r\n was at the end of the buffer, although it could have been some other characters, too.

Ended up just buying a license to a commercial serial port DLL.

Good luck!

scraimer
+1  A: 

Try checking IsOpen before reading.

Also, is there any chance the object containing _serialPort has been dereferenced and garbage collected? If you're never accessing _serialPort from another thread, try making it a private variable in Read().

Jon B
A: 

You have _serialPort declared as local SerialPort in the thread-starting code, so what is _serialPort referring to in Read() ?

Try creating the _serialPort object in the Read() method to be sure it's in the context of the same thread.

devio
A: 

It seemed like the RS232 cable (adapter) caused the crashes of the underlying serial port stream. Switched to an FTDI cable, that worked.

A look into the .NET Framework source code helped a lot. But I think the thrown ObjectDisposedException should be caught by the SerialPort, not by the user.

Stefan Teitge
A: 

1) Thread _readThread = new Thread(Read);

// is this a local definition of _readThread var in constructor?

// if so, after some time gabbage collector clear this var from memory, a disposed object

// shouldnot work (there is no such an object in memory).

// The same with SerialPort local var

// To work properly you should somewhere in class define a member

class foo

{

// ...

Thread _readThread;

SerialPort _serialPort;

bool bRunningReadTrhead=false;

//...

// which is static or instanced, than

public foo()

{

// ...

_serialPort = new SerialPort("COM1", 9600);

_serialPort.Parity = Parity.None;

_serialPort.DataBits = 8;

_serialPort.StopBits = StopBits.One;

_serialPort.Handshake = Handshake.None;

_serialPort.DtrEnable = true;

_serialPort.Open();

_readThread = new Thread(Read);

bRunningReadTrhead=true;

_readThread.Start();

//...

}

// creates a thread which will live a long time in loop:

private void Read()

{

while(bRunningReadTrhead)

{

      try
      {

          string message = _serialPort.ReadLine();

      }

      catch(Exception e)
      {
         Console.Write(e);
      }
   }

// exits a worker thread when you set global bool in false

}

// ...

}

// if you do not set a loop the thread also finish all jobs and become disposed