@@ -63,6 +63,8 @@ public static async Task TimeoutAfter(this Task task, TimeSpan timeout)
6363 class SocketFrameHandler : IFrameHandler
6464 {
6565 private readonly AmqpTcpEndpoint _endpoint ;
66+
67+
6668 // Socket poll timeout in ms. If the socket does not
6769 // become writeable in this amount of time, we throw
6870 // an exception.
@@ -78,19 +80,19 @@ class SocketFrameHandler : IFrameHandler
7880 private readonly byte [ ] _frameHeaderBuffer ;
7981 private bool _closed ;
8082 private ArrayPool < byte > _pool = ArrayPool < byte > . Shared ;
83+ private readonly bool _enableSynchronousWriteLoop ;
8184
8285 public SocketFrameHandler ( AmqpTcpEndpoint endpoint ,
8386 Func < AddressFamily , ITcpClient > socketFactory ,
84- TimeSpan connectionTimeout , TimeSpan readTimeout , TimeSpan writeTimeout )
87+ TimeSpan connectionTimeout , TimeSpan readTimeout , TimeSpan writeTimeout , bool enableSynchronousWriteLoop )
8588 {
8689 _endpoint = endpoint ;
90+ _enableSynchronousWriteLoop = enableSynchronousWriteLoop ;
8791 _frameHeaderBuffer = new byte [ 6 ] ;
8892 var channel = Channel . CreateUnbounded < ReadOnlyMemory < byte > > (
8993 new UnboundedChannelOptions
9094 {
91- AllowSynchronousContinuations = false ,
92- SingleReader = true ,
93- SingleWriter = false
95+ AllowSynchronousContinuations = false , SingleReader = true , SingleWriter = false
9496 } ) ;
9597
9698 _channelReader = channel . Reader ;
@@ -134,7 +136,15 @@ public SocketFrameHandler(AmqpTcpEndpoint endpoint,
134136 _writer = new BufferedStream ( netstream , _socket . Client . SendBufferSize ) ;
135137
136138 WriteTimeout = writeTimeout ;
137- _writerTask = Task . Run ( WriteLoop , CancellationToken . None ) ;
139+ if ( _enableSynchronousWriteLoop )
140+ {
141+ TaskCreationOptions tco = TaskCreationOptions . LongRunning | TaskCreationOptions . DenyChildAttach ;
142+ _writerTask = Task . Factory . StartNew ( SynchronousWriteLoop , CancellationToken . None , tco , TaskScheduler . Default ) ;
143+ }
144+ else
145+ {
146+ _writerTask = Task . Run ( WriteLoop , CancellationToken . None ) ;
147+ }
138148 }
139149
140150 public AmqpTcpEndpoint Endpoint
@@ -281,6 +291,24 @@ private async Task WriteLoop()
281291 }
282292 }
283293
294+ private void SynchronousWriteLoop ( )
295+ {
296+ while ( _channelReader . WaitToReadAsync ( ) . AsTask ( ) . Result )
297+ {
298+ _socket . Client . Poll ( _writeableStateTimeoutMicroSeconds , SelectMode . SelectWrite ) ;
299+ while ( _channelReader . TryRead ( out var memory ) )
300+ {
301+ if ( MemoryMarshal . TryGetArray ( memory , out ArraySegment < byte > segment ) &&
302+ segment . Array != null )
303+ {
304+ _writer . Write ( segment . Array , segment . Offset , segment . Count ) ;
305+ MemoryPool . Return ( segment . Array ) ;
306+ }
307+ }
308+ _writer . Flush ( ) ;
309+ }
310+ }
311+
284312 private static bool ShouldTryIPv6 ( AmqpTcpEndpoint endpoint )
285313 {
286314 return Socket . OSSupportsIPv6 && endpoint . AddressFamily != AddressFamily . InterNetwork ;
0 commit comments