计算机通过物理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已关闭。 Stack strace如下:
at Microsoft.Win32.UnsafeNativeMethods.GetOverlappedResult(SafeFileHandle hFile,NativeOverlapped lpOverlapped,Int32& lpNumberOfBytesTransferred,Boolean bWait) 在System.IO.Ports.SerialStream.EventLoopRunner.WaitForCommEvent() 在System.Threading.ThreadHelper.ThreadStart_Context(对象状态) 在System.Threading.ExecutionContext.Run(ExecutionContext executionContext,ContextCallback回调,对象状态) 在System.Threading.ThreadHelper.ThreadStart()*
有什么想法吗?这个问题被广泛报道,但通常涉及从PC上物理分离的设备。
答案 0 :(得分:1)
在阅读之前尝试检查IsOpen。
此外,是否有可能取消引用包含_serialPort的对象并收集垃圾?如果您从未从另一个线程访问_serialPort,请尝试在Read()中将其设为私有变量。
答案 1 :(得分:1)
似乎RS232电缆(适配器)导致底层串行端口流崩溃。切换到FTDI电缆,这是有效的。
查看.NET Framework源代码有很多帮助。但我认为抛出的ObjectDisposedException应该被SerialPort捕获,而不是由用户捕获。
答案 2 :(得分:0)
ObjectDisposedException表示有人在对象上调用Dispose。启动读线程后你在做什么?在退出程序之前,您是否等待读取线程完成?否则,读取线程可能仍在程序退出的情况下运行。
答案 3 :(得分:0)
大约一年前,我遇到了类似的事情。由于某种原因,读缓冲区末尾的某些字符会导致串口的C#接口自行关闭。它通常发生在\r\n
位于缓冲区的末尾,尽管它也可能是其他角色。
结束只购买商业串口DLL的许可证。
祝你好运!答案 4 :(得分:0)
你有_serialPort在线程启动代码中声明为本地SerialPort,那么在Read()中引用的是_serialPort是什么?
尝试在Read()方法中创建_serialPort对象,以确保它位于同一个线程的上下文中。
答案 5 :(得分:0)
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