Reputation: 23
I have an application that receives the data from an external laboratory unit trough a serial port. When I try to close the SerialPort, I get the following error:
System.IO.IOException: 'The I/O operation has been aborted because of either a thread exit or an application request.'
The data is read in event handler, raised by SerialPort
event DataReceived
- this runs in a separate thread by default (AFIK).
I subscribe to the Eventhandler
when connection to a SerialPort
is being established.
I unsubscribe from the EventHandler
before I close the serial port.
Code to close the connection (where _chronosPort
is an instance of a 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());
}
When invoking the Close()
method, I get:
'The I/O operation has been aborted because of either a thread exit or an application request.'
The error is thrown from EventHandler
's SerialPort ReadTo()
method, even though have unsubscribed from the event handler just before closing the serial port.
Upvotes: 2
Views: 967
Reputation: 2053
It's because you are using SerialPort
ReadTo
, the ReadTo
is blocking until it see's a character in the buffer stream you specified. So when you go to close the port, the ReadTo
is still waiting for a \r
. Unsubscribing isn't enough, as it's still running on it's own thread.
The fix would be to use ReadExisting()
, which will return all the characters in the buffer immediately. However, this will require more logic on your side in which you'll have to look for that end character yourself. Below is a simple way to use ReadExisting
, I build the string until I see my end character then I parse the string:
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);
}
}
}
Upvotes: 1