public override async Task OpenAsync(CancellationToken cancellationToken = default) { if (Open) { throw new MessageStreamOpenException("MessageStream already open"); } requests.Clear(); closeCounter = 0; closing = false; ReadChannelStats.Reset(); WriteChannelStats.Reset(); // Open the underlying stream first try { await base.OpenAsync(cancellationToken).ConfigureAwait(false); } catch (Exception) { Cleanup(); throw; } // Creates our read/write channels Channel <TInner> GetChannel <TInner>(ChannelOptions options) { if (options is UnboundedChannelOptions) { return(Channel.CreateUnbounded <TInner>((UnboundedChannelOptions)options)); } else { return(Channel.CreateBounded <TInner>((BoundedChannelOptions)options)); } } readChannel = GetChannel <MessageReadResult <T> >(concurrentOptions.ReaderChannelOptions); writeChannel = GetChannel <MessageWriteRequest>(concurrentOptions.WriterChannelOptions); readChannelTask = concurrentOptions.ChannelTaskFactory.StartNew(ReadLoopAsync, concurrentOptions.ReadChannelTaskOptions).Unwrap(); writeChannelTask = concurrentOptions.ChannelTaskFactory.StartNew(WriteLoopAsync, concurrentOptions.WriteChannelTaskOptions).Unwrap(); if (readChannelTask.IsCompleted && !readChannelTask.IsCompletedSuccessfully) { await CleanupOpenAsync().ConfigureAwait(false); throw readChannelTask.Exception; } if (writeChannelTask.IsCompleted && !writeChannelTask.IsCompletedSuccessfully) { await CleanupOpenAsync().ConfigureAwait(false); throw writeChannelTask.Exception; } readChannelCleanupTask = readChannel.Reader.Completion.ContinueWith((result) => ReadChannelCompleteAsync(result), TaskContinuationOptions.RunContinuationsAsynchronously); writeChannelCleanupTask = writeChannel.Reader.Completion.ContinueWith((result) => WriteChannelCompleteAsync(result), TaskContinuationOptions.RunContinuationsAsynchronously); }
private void Cleanup() { // Stop channels CompleteChannels(); // Reset stats ReadChannelStats.Reset(); WriteChannelStats.Reset(); // Complete any left over requests. foreach (var request in requests.Values) { request.resultTcs.TrySetResult(new MessageReadResult <T> { Error = true, Exception = new TaskCanceledException("Request timed out"), IsCompleted = true, Result = default,