/// <inheritdoc /> public async Task <byte[]> ReadAsync(int readSize, CancellationToken cancellationToken) { var readTask = new SocketPayloadReadTask(readSize, cancellationToken); await _readTaskQueue.EnqueueAsync(readTask, cancellationToken).ConfigureAwait(false); return(await readTask.Tcs.Task.ConfigureAwait(false)); }
private async Task ProcessReadTaskAsync(Stream stream, SocketPayloadReadTask readTask) { using (readTask) { var totalBytesRead = 0; var timer = new Stopwatch(); try { _configuration.OnReading?.Invoke(Endpoint, readTask.ReadSize); var buffer = new byte[readTask.ReadSize]; timer.Start(); while (totalBytesRead < readTask.ReadSize) { var readSize = readTask.ReadSize - totalBytesRead; _log.Debug(() => LogEvent.Create($"Reading ({readSize}? bytes) from {Endpoint}")); _configuration.OnReadingChunk?.Invoke(Endpoint, readTask.ReadSize, totalBytesRead, timer.Elapsed); var bytesRead = await stream.ReadAsync(buffer, totalBytesRead, readSize, readTask.CancellationToken).ConfigureAwait(false); totalBytesRead += bytesRead; var remainingBytes = readTask.ReadSize - totalBytesRead; _configuration.OnReadChunk?.Invoke(Endpoint, readTask.ReadSize, remainingBytes, bytesRead, timer.Elapsed); _log.Debug(() => LogEvent.Create($"Read {bytesRead} bytes from {Endpoint}{(readTask.CancellationToken.IsCancellationRequested ? " (cancelled)" : "")}")); if (bytesRead <= 0) { using (_client) { _client = null; if (_disposeToken.IsCancellationRequested) { _configuration.OnReadFailed?.Invoke(Endpoint, readTask.ReadSize, timer.Elapsed, new TaskCanceledException()); return; } throw new ConnectionException(Endpoint); } } } timer.Stop(); _configuration.OnRead?.Invoke(Endpoint, buffer, timer.Elapsed); readTask.Tcs.TrySetResult(buffer); totalBytesRead = 0; } catch (Exception ex) { timer.Stop(); _configuration.OnReadFailed?.Invoke(Endpoint, readTask.ReadSize, timer.Elapsed, ex); Exception exception = null; if (_disposeToken.IsCancellationRequested) { exception = new ObjectDisposedException($"Object is disposing (TcpSocket for {Endpoint})", ex); } else if ((_client == null || _client.Connected == false) && !(ex is ConnectionException)) { exception = new ConnectionException(Endpoint, ex); } if (totalBytesRead > 0) { readTask.Tcs.TrySetException(new PartialReadException(totalBytesRead, readTask.ReadSize, exception ?? ex)); } else { readTask.Tcs.TrySetException(exception ?? ex); } if (_disposeToken.IsCancellationRequested) { return; } if (exception != null) { throw exception; } throw; } } }