public override async Task <int> ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) { if (_chunks == null) { throw new ObjectDisposedException(nameof(DuplexStream)); } if (_chunks.Count == 0 && _writeClosed) { return(0); } SemaphoreLock semaphoreLock = await SemaphoreLock.GetLockAsync(_semaphore, cancellationToken); try { while (_chunks.Count == 0) { if (_writeClosed) { return(0); } semaphoreLock.Dispose(); semaphoreLock = null; await _newData.WaitAsync(cancellationToken); semaphoreLock = await SemaphoreLock.GetLockAsync(_semaphore, cancellationToken); } cancellationToken.ThrowIfCancellationRequested(); LinkedListNode <byte[]> node = _chunks.First; _chunks.Remove(node); byte[] value = node.Value; int toCopy = Math.Min(value.Length, count); Array.Copy(value, 0, buffer, offset, toCopy); if (toCopy != value.Length) { int remLength = value.Length - toCopy; var remainder = new byte[remLength]; Array.Copy(value, toCopy, remainder, 0, remLength); _chunks.AddFirst(remainder); } return(toCopy); } finally { semaphoreLock?.Dispose(); } }
public override async Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) { if (_writeClosed) { throw new InvalidOperationException(); } if (_chunks == null) { throw new ObjectDisposedException(nameof(DuplexStream)); } var insert = new byte[count]; Array.Copy(buffer, offset, insert, 0, count); using (await SemaphoreLock.GetLockAsync(_semaphore, cancellationToken)) { _chunks.AddLast(insert); } _newData.Set(); }