private void Flush(BufferingContext bufferingCtx) { if (bufferingCtx.Segment.Count != 0) { SendBuffer(bufferingCtx.Segment); } bufferingCtx.Reset(); }
private async Task SendBuffers() { var bufferingCtx = new BufferingContext(_maxBufferingSize, _maxBufferingTime, _sendBuffersCancellation.Token); while (true) { ArraySegment <byte> buffer; if (_sendBuffersCancellation.IsCancellationRequested) // disposing { if (!_chan.Reader.TryRead(out buffer)) { Flush(bufferingCtx); return; } } else { // the try block was not extract in its own method to avoid the cost of a new async state machine try { bufferingCtx.EnableTimeout(); buffer = await _chan.Reader.ReadAsync(bufferingCtx.BufferingCancellation); // make sure it doesn't get cancelled so it can be reused in the next iteration bufferingCtx.DisableTimeout(); } catch (OperationCanceledException) // timeout reached or disposing { if (!_sendBuffersCancellation.IsCancellationRequested) // timeout { Flush(bufferingCtx); } // continue in both case. If timeout, reloop to retry getting a value. If disposing reloop to dequeue all buffers continue; } } if (buffer.Count > _maxBufferingSize) { SendBuffer(buffer); ArrayPool <byte> .Shared.Return(buffer.Array); continue; } if (!bufferingCtx.Fits(buffer)) { Flush(bufferingCtx); } bufferingCtx.Append(buffer); ArrayPool <byte> .Shared.Return(buffer.Array); } }
private async Task <string> ReceiveLoopAsync(BufferingContext bufferingContext, CancellationToken cancellationToken, int loop) { using (bufferingContext) { var encoding = bufferingContext.Encoding; var bufferBytes = bufferingContext.BufferBytes; var bufferChars = bufferingContext.BufferChars; var sb = bufferingContext.StringBuilder; try { string response = null; while ((loop == -1 || --loop >= 0) && !cancellationToken.IsCancellationRequested) { response = await ReceiveMessageAsync(cancellationToken, bufferBytes, bufferChars, encoding, sb); sb = sb.Clear(); } if (cancellationToken.IsCancellationRequested) { return(await TaskEx.FromCanceled <string>(cancellationToken)); } return(response); } catch (AggregateException ex) { ErrorReceived?.Invoke(this, new SocketErrorEventArgs { Exception = ex.Flatten() }); } catch (Exception ex) { ErrorReceived?.Invoke(this, new SocketErrorEventArgs { Exception = ex }); } } return(await Task.FromResult(string.Empty)); }
private Task <string> ReceiveLoopAsync(BufferingContext bufferingContext, CancellationToken cancellationToken, int loop) { string response = null; return(TaskEx.AsyncLoopTask(() => { cancellationToken.ThrowIfCancellationRequested(); if (loop == -1 || --loop >= 0) { return TaskEx.FromResult(Flow <string> .Return(response)); } var encoding = bufferingContext.Encoding; var bufferBytes = bufferingContext.BufferBytes; var bufferChars = bufferingContext.BufferChars; var sb = bufferingContext.StringBuilder; return ReceiveMessageAsync(cancellationToken, bufferBytes, bufferChars, encoding, sb).ContinueWith(t => { response = t.Result; sb.Length = 0; return Flow <string> .Continue(); }, cancellationToken); }).ContinueWithTask(task => { if (cancellationToken.IsCancellationRequested) { return TaskEx.FromCanceled <string>(cancellationToken); } return TaskEx.FromResult(task.Result); }, cancellationToken) .CatchWith <string, Exception>(ex => ErrorReceived?.Invoke(this, new SocketErrorEventArgs { Exception = ex })) .UsingWith(bufferingContext)); }