我正如本文If you must use .NET System.IO.Ports.SerialPort中所建议的那样使用BaseStream使用.NET System.IO.Ports.SerialPort
但是当我尝试关闭端口或baseStream时,会引发 System.InvalidOperationException ,说" BaseStream仅在端口打开时可用"
这是我的代码:
private void ActionStarted()
{
//ajusta el puerto
setupSerial();
serial.Open(); //conecta al plc
byte[] buffer = new byte[15];
Action kickoffRead = null;
if (serial.IsOpen)
{
kickoffRead = delegate()
{
serial.BaseStream.BeginRead(buffer, 0, buffer.Length,
delegate(IAsyncResult ar)
{
try
{
int actualLength = serial.BaseStream.EndRead(ar);
byte[] received = new byte[actualLength];
Buffer.BlockCopy(buffer, 0, received, 0, actualLength);
raiseAppSerialDataEvent(received);
}
catch
{
//do something
}
kickoffRead();
}, null);
};
kickoffRead();
}
}
//<-- here is where the error occurs -->
private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
serial.BaseStream.Flush();
serial.BaseStream.Close();
serial.Close();
}
我在某处看到串口应该在不同的线程上关闭,但我找不到,所以任何想法?
谢谢!
答案 0 :(得分:2)
我面临与你描述的问题相同的问题。基本上我解决了在调用读取操作之前正确处理串口资源和检查端口状态的问题。这是打开端口,读取和关闭它的完整代码。
public bool Open()
{
bool result = false;
try
{
this.serialPort.Open();
result = true;
startReading = StartAsyncSerialReading;
startReading();
}
catch (Exception)
{
this.Close();
result = false;
}
return result;
}
private void StartAsyncSerialReading()
{
byte[] buffer = new byte[bufferLength];
serialPort.BaseStream.BeginRead(buffer, 0, bufferLength, delegate(IAsyncResult ar)
{
try
{
if (serialPort.IsOpen)
{
actualReadLength = serialPort.BaseStream.EndRead(ar);
received = new byte[actualReadLength];
DoYourStuffWithDataBuffer();
}
}
catch (IOException exc)
{
//handleAppSerialError(exc);
}
if (serialPort.IsOpen)
startReading();
}, null);
}
protected Stream GetStream()
{
return this.serialPort.BaseStream;
}
public void Dispose()
{
this.Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (!this.disposed)
{
if (disposing)
this.serialPort.Dispose();
this.disposed = true;
}
}
public void Close()
{
this.serialPort.Close();
this.Dispose();
}
答案 1 :(得分:0)
正如Luca正确指出的那样,您应该在阅读之前检查串口的状态。
您得到异常,因为您的阅读线程(委托)尝试使用已关闭的串行端口。
此外,在关闭串口之前,请使用Dispose()方法。通常,如果一个对象继承了IDisposable,那么当你不再需要它时,最好配置它,特别是如果对象使用非托管资源,比如串口。即使在C#中,不管理非托管资源也会导致内存泄漏(垃圾收集器不会收集非托管资源!)