@@ -345,7 +345,7 @@ public async Task UploadStreamCancelationSendsStreamComplete()
345
345
var complete = await connection . ReadSentJsonAsync ( ) . OrTimeout ( ) ;
346
346
Assert . Equal ( HubProtocolConstants . CompletionMessageType , complete [ "type" ] ) ;
347
347
Assert . EndsWith ( "canceled by client." , ( ( string ) complete [ "error" ] ) ) ;
348
- }
348
+ }
349
349
}
350
350
351
351
[ Fact ]
@@ -414,6 +414,52 @@ bool ExpectedErrors(WriteContext writeContext)
414
414
}
415
415
}
416
416
417
+ [ Fact ]
418
+ public async Task CanAwaitInvokeFromOnHandlerWithServerClosingConnection ( )
419
+ {
420
+ using ( StartVerifiableLog ( ) )
421
+ {
422
+ var connection = new TestConnection ( ) ;
423
+ var hubConnection = CreateHubConnection ( connection , loggerFactory : LoggerFactory ) ;
424
+ await hubConnection . StartAsync ( ) . OrTimeout ( ) ;
425
+
426
+ var tcs = new TaskCompletionSource < object > ( TaskCreationOptions . RunContinuationsAsynchronously ) ;
427
+ hubConnection . On < string > ( "Echo" , async msg =>
428
+ {
429
+ try
430
+ {
431
+ // This should be canceled when the connection is closed
432
+ await hubConnection . InvokeAsync < string > ( "Echo" , msg ) . OrTimeout ( ) ;
433
+ }
434
+ catch ( Exception ex )
435
+ {
436
+ tcs . SetException ( ex ) ;
437
+ return ;
438
+ }
439
+
440
+ tcs . SetResult ( null ) ;
441
+ } ) ;
442
+
443
+ var closedTcs = new TaskCompletionSource < object > ( TaskCreationOptions . RunContinuationsAsynchronously ) ;
444
+ hubConnection . Closed += _ =>
445
+ {
446
+ closedTcs . SetResult ( null ) ;
447
+
448
+ return Task . CompletedTask ;
449
+ } ;
450
+
451
+ await connection . ReceiveJsonMessage ( new { type = HubProtocolConstants . InvocationMessageType , target = "Echo" , arguments = new object [ ] { "42" } } ) . OrTimeout ( ) ;
452
+
453
+ // Read sent message first to make sure invoke has been processed and is waiting for a response
454
+ await connection . ReadSentJsonAsync ( ) . OrTimeout ( ) ;
455
+ await connection . ReceiveJsonMessage ( new { type = HubProtocolConstants . CloseMessageType } ) . OrTimeout ( ) ;
456
+
457
+ await closedTcs . Task . OrTimeout ( ) ;
458
+
459
+ await Assert . ThrowsAsync < TaskCanceledException > ( ( ) => tcs . Task . OrTimeout ( ) ) ;
460
+ }
461
+ }
462
+
417
463
private class SampleObject
418
464
{
419
465
public SampleObject ( string foo , int bar )
0 commit comments