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);
            }
        }
예제 #3
0
        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));
        }
예제 #4
0
        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));
        }