Открытый SerialPort вылетает приложение C#

Компьютер подключен к измерительному устройству через физический COM1. У меня есть простая форма, где я открываю последовательный порт, говорю устройству, что я жив, и иногда устройство отправляет данные. (каждые несколько минут)

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");

Функция чтения (которая работает):

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

Примерно через минуту приложение вылетает (даже во время отладки). Он сообщает об исключении ObjectDisposedException (для основного потока?). Сообщение сообщает, что SafeHandle был закрыт. Стек стрейса находится ниже:

в Microsoft.Win32.UnsafeNativeMethods.GetOverlappedResult (SafeFileHandle hFile, NativeOverlapped lpOverlapped, Int32 & lpNumberOfBytesTransferred, логическое значение bWait) в System.IO.Ports.SerialStream.EntthText.Threading.ExecutionContext.Run(ExecutionContext executeContext, обратный вызов ContextCallback, состояние объекта) в System.Threading.ThreadHelper.ThreadStart()*

Есть идеи? О проблеме сообщают широко, но обычно это устройство физически отсоединено от ПК.

6 ответов

Решение

Казалось, что кабель RS232 (адаптер) вызвал сбои основного потока последовательного порта. Переключился на кабель FTDI, который работал.

Просмотр исходного кода.NET Framework очень помог. Но я думаю, что брошенное ObjectDisposedException должно быть перехвачено SerialPort, а не пользователем.

Попробуйте проверить IsOpen перед чтением.

Кроме того, есть ли вероятность разыменования объекта, содержащего _serialPort, и сбора мусора? Если вы никогда не обращаетесь к _serialPort из другого потока, попробуйте сделать его закрытой переменной в Read().

У вас _serialPort, объявленный как локальный SerialPort в коде, запускающем поток, так на что же ссылается _serialPort в Read()?

Попробуйте создать объект _serialPort в методе Read (), чтобы убедиться, что он находится в контексте того же потока.

У меня было что-то похожее со мной около года назад. По какой-то причине некоторые символы в конце буфера чтения могут привести к тому, что интерфейс C# к последовательному порту закроется сам. Обычно это происходит, когда \r\n был в конце буфера, хотя это могли быть и другие символы.

Закончилось просто покупкой лицензии на коммерческий последовательный порт DLL.

Удачи!

ObjectDisposedException означает, что кто-то вызвал Dispose для объекта. Что вы делаете после запуска темы чтения? Вы ждете завершения чтения, прежде чем выйти из программы? В противном случае, возможно, поток чтения все еще работает с выходом из программы.

1) Тема _readThread = новая тема (чтение);

// 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
Другие вопросы по тегам