@@ -293,16 +293,20 @@ await SendInvocationError(hubMethodInvocationMessage.InvocationId, connection,
293
293
{
294
294
var result = await ExecuteHubMethod ( methodExecutor , hub , arguments ) ;
295
295
296
- if ( ! TryGetStreamingEnumerator ( connection , hubMethodInvocationMessage . InvocationId , descriptor , result , out var enumerator , ref cts ) )
296
+ if ( result == null )
297
297
{
298
298
Log . InvalidReturnValueFromStreamingMethod ( _logger , methodExecutor . MethodInfo . Name ) ;
299
299
await SendInvocationError ( hubMethodInvocationMessage . InvocationId , connection ,
300
- $ "The value returned by the streaming method '{ methodExecutor . MethodInfo . Name } ' is not a ChannelReader<>.") ;
300
+ $ "The value returned by the streaming method '{ methodExecutor . MethodInfo . Name } ' is not a ChannelReader<> or IAsyncEnumerable<> .") ;
301
301
return ;
302
302
}
303
303
304
+ cts = cts ?? CancellationTokenSource . CreateLinkedTokenSource ( connection . ConnectionAborted ) ;
305
+ connection . ActiveRequestCancellationSources . TryAdd ( hubMethodInvocationMessage . InvocationId , cts ) ;
306
+ var enumerable = descriptor . FromReturnedStream ( result , cts . Token ) ;
307
+
304
308
Log . StreamingResult ( _logger , hubMethodInvocationMessage . InvocationId , methodExecutor ) ;
305
- _ = StreamResultsAsync ( hubMethodInvocationMessage . InvocationId , connection , enumerator , scope , hubActivator , hub , cts , hubMethodInvocationMessage ) ;
309
+ _ = StreamResultsAsync ( hubMethodInvocationMessage . InvocationId , connection , enumerable , scope , hubActivator , hub , cts , hubMethodInvocationMessage ) ;
306
310
}
307
311
308
312
else if ( string . IsNullOrEmpty ( hubMethodInvocationMessage . InvocationId ) )
@@ -393,17 +397,17 @@ private ValueTask CleanupInvocation(HubConnectionContext connection, HubMethodIn
393
397
return scope . DisposeAsync ( ) ;
394
398
}
395
399
396
- private async Task StreamResultsAsync ( string invocationId , HubConnectionContext connection , IAsyncEnumerator < object > enumerator , IServiceScope scope ,
400
+ private async Task StreamResultsAsync ( string invocationId , HubConnectionContext connection , IAsyncEnumerable < object > enumerable , IServiceScope scope ,
397
401
IHubActivator < THub > hubActivator , THub hub , CancellationTokenSource streamCts , HubMethodInvocationMessage hubMethodInvocationMessage )
398
402
{
399
403
string error = null ;
400
404
401
405
try
402
406
{
403
- while ( await enumerator . MoveNextAsync ( ) )
407
+ await foreach ( var streamItem in enumerable )
404
408
{
405
409
// Send the stream item
406
- await connection . WriteAsync ( new StreamItemMessage ( invocationId , enumerator . Current ) ) ;
410
+ await connection . WriteAsync ( new StreamItemMessage ( invocationId , streamItem ) ) ;
407
411
}
408
412
}
409
413
catch ( ChannelClosedException ex )
@@ -422,8 +426,6 @@ private async Task StreamResultsAsync(string invocationId, HubConnectionContext
422
426
}
423
427
finally
424
428
{
425
- ( enumerator as IDisposable ) ? . Dispose ( ) ;
426
-
427
429
await CleanupInvocation ( connection , hubMethodInvocationMessage , hubActivator , hub , scope ) ;
428
430
429
431
// Dispose the linked CTS for the stream.
@@ -502,10 +504,10 @@ private static async Task<bool> IsHubMethodAuthorizedSlow(IServiceProvider provi
502
504
return authorizationResult . Succeeded ;
503
505
}
504
506
505
- private async Task < bool > ValidateInvocationMode ( HubMethodDescriptor hubMethodDescriptor , bool isStreamedInvocation ,
507
+ private async Task < bool > ValidateInvocationMode ( HubMethodDescriptor hubMethodDescriptor , bool isStreamResponse ,
506
508
HubMethodInvocationMessage hubMethodInvocationMessage , HubConnectionContext connection )
507
509
{
508
- if ( hubMethodDescriptor . IsStreamable && ! isStreamedInvocation )
510
+ if ( hubMethodDescriptor . IsStreamResponse && ! isStreamResponse )
509
511
{
510
512
// Non-null/empty InvocationId? Blocking
511
513
if ( ! string . IsNullOrEmpty ( hubMethodInvocationMessage . InvocationId ) )
@@ -518,7 +520,7 @@ await connection.WriteAsync(CompletionMessage.WithError(hubMethodInvocationMessa
518
520
return false ;
519
521
}
520
522
521
- if ( ! hubMethodDescriptor . IsStreamable && isStreamedInvocation )
523
+ if ( ! hubMethodDescriptor . IsStreamResponse && isStreamResponse )
522
524
{
523
525
Log . NonStreamingMethodCalledWithStream ( _logger , hubMethodInvocationMessage ) ;
524
526
await connection . WriteAsync ( CompletionMessage . WithError ( hubMethodInvocationMessage . InvocationId ,
@@ -530,26 +532,6 @@ await connection.WriteAsync(CompletionMessage.WithError(hubMethodInvocationMessa
530
532
return true ;
531
533
}
532
534
533
- private bool TryGetStreamingEnumerator ( HubConnectionContext connection , string invocationId , HubMethodDescriptor hubMethodDescriptor , object result , out IAsyncEnumerator < object > enumerator , ref CancellationTokenSource streamCts )
534
- {
535
- if ( result != null )
536
- {
537
- if ( hubMethodDescriptor . IsChannel )
538
- {
539
- if ( streamCts == null )
540
- {
541
- streamCts = CancellationTokenSource . CreateLinkedTokenSource ( connection . ConnectionAborted ) ;
542
- }
543
- connection . ActiveRequestCancellationSources . TryAdd ( invocationId , streamCts ) ;
544
- enumerator = hubMethodDescriptor . FromChannel ( result , streamCts . Token ) ;
545
- return true ;
546
- }
547
- }
548
-
549
- enumerator = null ;
550
- return false ;
551
- }
552
-
553
535
private void DiscoverHubMethods ( )
554
536
{
555
537
var hubType = typeof ( THub ) ;
0 commit comments