打开的SerialPort崩溃了C#应用程序

时间:2009-04-28 11:31:01

标签: c# .net serial-port objectdisposedexception

计算机通过物理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上物理分离的设备。

6 个答案:

答案 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