Task <int> ProcessRead(byte[] buffer, int offset, int size, CancellationToken cancellationToken) { if (read_eof) { return(Task.FromResult(0)); } if (cancellationToken.IsCancellationRequested) { return(Task.FromCanceled <int> (cancellationToken)); } return(HttpWebRequest.RunWithTimeout( ct => innerStream.ReadAsync(buffer, offset, size, ct), ReadTimeout, () => { Operation.Abort(); innerStream.Dispose(); }, cancellationToken)); }
public override async Task <int> ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) { WebConnection.Debug($"{ME} READ ASYNC"); cancellationToken.ThrowIfCancellationRequested(); if (buffer == null) { throw new ArgumentNullException(nameof(buffer)); } int length = buffer.Length; if (offset < 0 || length < offset) { throw new ArgumentOutOfRangeException(nameof(offset)); } if (count < 0 || (length - offset) < count) { throw new ArgumentOutOfRangeException(nameof(count)); } if (Interlocked.CompareExchange(ref nestedRead, 1, 0) != 0) { throw new InvalidOperationException("Invalid nested call."); } var completion = new WebCompletionSource(); while (!cancellationToken.IsCancellationRequested) { /* * 'currentRead' is set by ReadAllAsync(). */ var oldCompletion = Interlocked.CompareExchange(ref pendingRead, completion, null); WebConnection.Debug($"{ME} READ ASYNC #1: {oldCompletion != null}"); if (oldCompletion == null) { break; } await oldCompletion.WaitForCompletion().ConfigureAwait(false); } WebConnection.Debug($"{ME} READ ASYNC #2: {totalRead} {contentLength}"); int oldBytes = 0, nbytes = 0; Exception throwMe = null; try { // FIXME: NetworkStream.ReadAsync() does not support cancellation. (oldBytes, nbytes) = await HttpWebRequest.RunWithTimeout( ct => ProcessRead(buffer, offset, count, ct), ReadTimeout, () => { Operation.Abort(); InnerStream.Dispose(); }, () => Operation.Aborted, cancellationToken).ConfigureAwait(false); } catch (Exception e) { throwMe = GetReadException(WebExceptionStatus.ReceiveFailure, e, "ReadAsync"); } WebConnection.Debug($"{ME} READ ASYNC #3: {totalRead} {contentLength} - {oldBytes} {nbytes} {throwMe?.Message}"); if (throwMe != null) { lock (locker) { completion.TrySetException(throwMe); pendingRead = null; nestedRead = 0; } closed = true; Operation.Finish(false, throwMe); throw throwMe; } lock (locker) { pendingRead.TrySetCompleted(); pendingRead = null; nestedRead = 0; } if (totalRead >= contentLength && !nextReadCalled) { WebConnection.Debug($"{ME} READ ASYNC - READ COMPLETE: {oldBytes} {nbytes} - {totalRead} {contentLength} {nextReadCalled}"); if (!nextReadCalled) { nextReadCalled = true; Operation.Finish(true); } } return(oldBytes + nbytes); }
public override async Task <int> ReadAsync(byte[] buffer, int offset, int size, CancellationToken cancellationToken) { WebConnection.Debug($"{ME} READ ASYNC"); cancellationToken.ThrowIfCancellationRequested(); if (buffer == null) { throw new ArgumentNullException(nameof(buffer)); } int length = buffer.Length; if (offset < 0 || length < offset) { throw new ArgumentOutOfRangeException(nameof(offset)); } if (size < 0 || (length - offset) < size) { throw new ArgumentOutOfRangeException(nameof(size)); } if (Interlocked.CompareExchange(ref nestedRead, 1, 0) != 0) { throw new InvalidOperationException("Invalid nested call."); } var myReadTcs = new TaskCompletionSource <int> (); while (!cancellationToken.IsCancellationRequested) { /* * 'readTcs' is set by ReadAllAsync(). */ var oldReadTcs = Interlocked.CompareExchange(ref readTcs, myReadTcs, null); WebConnection.Debug($"{ME} READ ASYNC #1: {oldReadTcs != null}"); if (oldReadTcs == null) { break; } await oldReadTcs.Task.ConfigureAwait(false); } WebConnection.Debug($"{ME} READ ASYNC #2: {totalRead} {contentLength}"); int nbytes = 0; Exception throwMe = null; try { // FIXME: NetworkStream.ReadAsync() does not support cancellation. nbytes = await HttpWebRequest.RunWithTimeout( ct => ProcessRead(buffer, offset, size, ct), ReadTimeout, () => { Operation.Abort(); InnerStream.Dispose(); }).ConfigureAwait(false); } catch (Exception e) { throwMe = GetReadException(WebExceptionStatus.ReceiveFailure, e, "ReadAsync"); } WebConnection.Debug($"{ME} READ ASYNC #3: {totalRead} {contentLength} - {nbytes} {throwMe?.Message}"); if (throwMe != null) { lock (locker) { myReadTcs.TrySetException(throwMe); readTcs = null; nestedRead = 0; } closed = true; Operation.CompleteResponseRead(false, throwMe); throw throwMe; } lock (locker) { readTcs.TrySetResult(nbytes); readTcs = null; nestedRead = 0; } if (totalRead >= contentLength && !nextReadCalled) { WebConnection.Debug($"{ME} READ ASYNC - READ COMPLETE: {nbytes} - {totalRead} {contentLength} {nextReadCalled}"); if (!nextReadCalled) { nextReadCalled = true; Operation.CompleteResponseRead(true); } } return(nbytes); }