private async Task DoSend() { Exception shutdownReason = null; Exception unexpectedError = null; try { await ProcessSends(); } catch (SocketException ex) when(IsConnectionResetError(ex.SocketErrorCode)) { shutdownReason = new ConnectionResetException(ex.Message, ex); _trace.ConnectionReset(ConnectionId); } catch (Exception ex) when((ex is SocketException socketEx && IsConnectionAbortError(socketEx.SocketErrorCode)) || ex is ObjectDisposedException) { // This should always be ignored since Shutdown() must have already been called by Abort(). shutdownReason = ex; } catch (Exception ex) { shutdownReason = ex; unexpectedError = ex; _trace.ConnectionError(ConnectionId, unexpectedError); } finally { Shutdown(shutdownReason); // Complete the output after disposing the socket Output.Complete(unexpectedError); // Cancel any pending flushes so that the input loop is un-paused Input.CancelPendingFlush(); } }