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();
}
我在某处读到串行端口应该在不同的线程上关闭,但我找不到,所以有什么想法吗?
谢谢!!
我面临着与您描述的相同的问题。基本上,我通过正确处理串行端口资源并在调用读取操作之前检查端口状态来解决。这是打开端口、读取并关闭端口的完整代码。
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();
}
正如 Luca 正确指出的那样,您应该在读取之前检查串行端口的状态。
您收到异常是因为您的读取线程(委托)尝试使用关闭的串行端口。
此外,在关闭串行端口之前使用 Dispose() 方法。通常,如果对象继承了 IDisposable,则最好在不再需要它时释放它,尤其是在对象使用串行端口等非托管资源时。即使在 C# 中,不释放非托管资源也会导致内存泄漏(垃圾回收器不会收集非托管资源!