我有一个应用程序,它通过串行端口从外部实验室单元接收数据。当我尝试关闭SerialPort时,出现以下错误:
System.IO.IOException:'由于线程退出或应用程序请求,I / O操作已中止。'
在事件处理程序中读取数据,由SerialPort
事件DataReceived
引发-默认情况下,该数据在单独的线程(AFIK)中运行。
与Eventhandler
建立连接后,我订阅了SerialPort
。
在关闭串行端口之前,我要退订EventHandler
。
关闭连接的代码(其中_chronosPort
是SerialPort
的实例):
public void CloseConnection()
{
if (_connected)
{
_chronosPort.DataReceived -= OnDataReceived;
_chronosPort.Close();
_connected = false;
}
}
private void OnDataReceived(object sender, SerialDataReceivedEventArgs e)
{
var sp = (SerialPort) sender;
RawSample = sp.ReadTo("\r");
SampleFactory sampleFactory = new SampleFactory(RawSample, new SampleTypeExtractor());
OnSampleReady(sampleFactory.GetSample());
}
调用Close()
方法时,我得到:
“由于线程退出或应用程序请求,I / O操作已中止。”
EventHandler
的{{1}}方法引发了错误,即使在关闭串行端口之前已取消订阅事件处理程序。
答案 0 :(得分:0)
这是因为您正在使用SerialPort
ReadTo
,ReadTo
一直阻塞,直到在您指定的缓冲流中看到一个字符为止。因此,当您关闭端口时,ReadTo
仍在等待\r
。取消订阅是不够的,因为它仍在自己的线程上运行。
解决方法是使用ReadExisting()
,它将立即返回缓冲区中的所有字符。但是,这将需要您方面的更多逻辑,您必须自己寻找该最终角色。以下是使用ReadExisting
的简单方法,我先构建字符串,直到看到结束符,然后解析字符串:
StringBuilder sb = new StringBuilder();
private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
string Data = serialPort1.ReadExisting();
foreach (char c in Data)
{
if (c == '\r')
{
sb.Append(c);
CurrentLine = sb.ToString();
sb.Clear();
SampleFactory sampleFactory = new SampleFactory(CurrentLine, new SampleTypeExtractor());
OnSampleReady(sampleFactory.GetSample());
}
else
{
sb.Append(c);
}
}
}