private void WriteResponseInOrder(IChannelHandlerContext ctx, ThriftMessage response, long responseSequenceId) { // Ensure responses to requests are written in the same order the requests // were received. lock (_responseMap) { long currentResponseId = Interlocked.Read(ref _lastResponseWrittenId) + 1; if (responseSequenceId != currentResponseId) { // This response is NOT next in line of ordered responses, save it to // be sent later, after responses to all earlier requests have been // sent. _responseMap[responseSequenceId] = response; } else { // This response was next in line, write this response now, and see if // there are others next in line that should be sent now as well. do { ctx.Channel.WriteAndFlushAsync(response).GetAwaiter().GetResult(); Interlocked.Increment(ref _lastResponseWrittenId); ++currentResponseId; response = _responseMap.RemoveAndGet(currentResponseId); } while (null != response); // Now that we've written some responses, check if reads should be unblocked if (DispatcherContext.IsChannelReadBlocked(ctx)) { long lastRequestSequenceId = Interlocked.Read(ref _dispatcherSequenceId); if (lastRequestSequenceId <= Interlocked.Read(ref _lastResponseWrittenId) + _queuedResponseLimit) { DispatcherContext.UnblockChannelReads(ctx); } } } } }
public override void ChannelActive(IChannelHandlerContext context) { // Reads always start out unblocked DispatcherContext.UnblockChannelReads(context); base.ChannelActive(context); }