@@ -63,6 +63,8 @@ public static async Task TimeoutAfter(this Task task, TimeSpan timeout)
63
63
class SocketFrameHandler : IFrameHandler
64
64
{
65
65
private readonly AmqpTcpEndpoint _endpoint ;
66
+
67
+
66
68
// Socket poll timeout in ms. If the socket does not
67
69
// become writeable in this amount of time, we throw
68
70
// an exception.
@@ -78,19 +80,19 @@ class SocketFrameHandler : IFrameHandler
78
80
private readonly byte [ ] _frameHeaderBuffer ;
79
81
private bool _closed ;
80
82
private ArrayPool < byte > _pool = ArrayPool < byte > . Shared ;
83
+ private readonly bool _enableSynchronousWriteLoop ;
81
84
82
85
public SocketFrameHandler ( AmqpTcpEndpoint endpoint ,
83
86
Func < AddressFamily , ITcpClient > socketFactory ,
84
- TimeSpan connectionTimeout , TimeSpan readTimeout , TimeSpan writeTimeout )
87
+ TimeSpan connectionTimeout , TimeSpan readTimeout , TimeSpan writeTimeout , bool enableSynchronousWriteLoop )
85
88
{
86
89
_endpoint = endpoint ;
90
+ _enableSynchronousWriteLoop = enableSynchronousWriteLoop ;
87
91
_frameHeaderBuffer = new byte [ 6 ] ;
88
92
var channel = Channel . CreateUnbounded < ReadOnlyMemory < byte > > (
89
93
new UnboundedChannelOptions
90
94
{
91
- AllowSynchronousContinuations = false ,
92
- SingleReader = true ,
93
- SingleWriter = false
95
+ AllowSynchronousContinuations = false , SingleReader = true , SingleWriter = false
94
96
} ) ;
95
97
96
98
_channelReader = channel . Reader ;
@@ -134,7 +136,15 @@ public SocketFrameHandler(AmqpTcpEndpoint endpoint,
134
136
_writer = new BufferedStream ( netstream , _socket . Client . SendBufferSize ) ;
135
137
136
138
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
+ }
138
148
}
139
149
140
150
public AmqpTcpEndpoint Endpoint
@@ -281,6 +291,24 @@ private async Task WriteLoop()
281
291
}
282
292
}
283
293
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
+
284
312
private static bool ShouldTryIPv6 ( AmqpTcpEndpoint endpoint )
285
313
{
286
314
return Socket . OSSupportsIPv6 && endpoint . AddressFamily != AddressFamily . InterNetwork ;
0 commit comments