private void ReadBuffer(IAsyncResult ar) {
int byteLen;
try {
byteLen = stream.EndRead(ar);
}
catch (IOException ) {
// We should ideally consume errors from operations getting cancelled
// so that we don't crash the unsuspecting parent with an unhandled exc.
// This seems to come in 2 forms of exceptions (depending on platform and scenario),
// namely OperationCanceledException and IOException (for errorcode that we don't
// map explicitly).
byteLen = 0; // Treat this as EOF
}
catch (OperationCanceledException ) {
// We should consume any OperationCanceledException from child read here
// so that we don't crash the parent with an unhandled exc
byteLen = 0; // Treat this as EOF
}
if (byteLen == 0) {
// We're at EOF, we won't call this function again from here on.
lock(messageQueue) {
if( sb.Length != 0) {
messageQueue.Enqueue(sb.ToString());
sb.Length = 0;
}
messageQueue.Enqueue(null);
}
try {
// UserCallback could throw, we should still set the eofEvent
FlushMessageQueue();
}
finally {
eofEvent.Set();
}
} else {
int charLen = decoder.GetChars(byteBuffer, 0, byteLen, charBuffer, 0);
sb.Append(charBuffer, 0, charLen);
GetLinesFromStringBuilder();
stream.BeginRead(byteBuffer, 0 , byteBuffer.Length, new AsyncCallback(ReadBuffer), null);
}
}