@@ -588,16 +588,30 @@ internal static int ReadIntForHandshake(this PipeStream stream, byte? byteToAcce
588588
589589#if ! TASKHOST
590590 /// <summary>
591- /// Allow interop with EAP / Event-based wait handles without additional allocations.
592- /// By signalling an external reset event, this allows use of WaitHandle.WaitAny() in non-async/await contexts.
591+ /// This is intended to get around state-machine and wait handle allocations on .NET Framework for async reads.
592+ /// Prefer ReadAsync() when the read is expected to complete synchronously, or if the bytes to read are greater
593+ /// than the stream's buffer and will require multiple reads (e.g. the packet body).
594+ /// By signalling an external reset event, this also allows use of WaitHandle.WaitAny() in non-async/await contexts.
593595 /// </summary>
594- internal static async ValueTask< int > ReadAsync ( Stream stream , byte [ ] buffer , int bytesToRead , AutoResetEvent autoResetEvent )
596+ internal static ValueTask< int > ReadExactlyAsync ( Stream stream , byte [ ] buffer , int bytesToRead , AutoResetEvent autoResetEvent = null )
595597 {
596- // Signal to the caller only after the read is complete.
597- int result = await ReadAsync ( stream , buffer , bytesToRead ) . ConfigureAwait ( false ) ;
598- _ = autoResetEvent . Set ( ) ;
598+ Task < int > readTask = stream. ReadAsync ( buffer , 0 , bytesToRead ) ;
599599
600- return result ;
600+ // If the task completed synchronously, directly return the result.
601+ if ( readTask . IsCompleted )
602+ {
603+ _ = autoResetEvent? . Set ( ) ;
604+ return new ValueTask< int > ( readTask . Result ) ;
605+ }
606+
607+ // Otherwise, a Task has been allocated and we'll need to set a callback.
608+ readTask = readTask . ContinueWith ( static ( completedTask , state ) =>
609+ {
610+ _ = ( ( AutoResetEvent ) state ) ? . Set ( ) ;
611+ return completedTask . Result ;
612+ } , autoResetEvent , TaskContinuationOptions . ExecuteSynchronously ) ;
613+
614+ return new ValueTask< int > ( readTask ) ;
601615 }
602616
603617 internal static async ValueTask < int > ReadAsync ( Stream stream , byte [ ] buffer , int bytesToRead )
0 commit comments