Открытый 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