diff --git a/src/SignalR/clients/csharp/Client.Core/src/HubConnection.cs b/src/SignalR/clients/csharp/Client.Core/src/HubConnection.cs index e8d35d753fc123a3c9551ad5b1565212bf9a368e..392d0ac7c8f4227b79a85dd0c966070f31fd5b93 100644 --- a/src/SignalR/clients/csharp/Client.Core/src/HubConnection.cs +++ b/src/SignalR/clients/csharp/Client.Core/src/HubConnection.cs @@ -501,6 +501,11 @@ namespace Microsoft.AspNetCore.SignalR.Client { connectionState.Stopping = true; } + else + { + // Reset StopCts if there isn't an active connection so that the next StartAsync wont immediately fail due to the token being canceled + _state.StopCts = new CancellationTokenSource(); + } if (disposing) { diff --git a/src/SignalR/clients/csharp/Client/test/UnitTests/HubConnectionTests.ConnectionLifecycle.cs b/src/SignalR/clients/csharp/Client/test/UnitTests/HubConnectionTests.ConnectionLifecycle.cs index 3c669ef94dd24e50b8fbd3a9d54bda02483c6f88..f1d191ee8ca85e4990b553861df66c40dfb5c48f 100644 --- a/src/SignalR/clients/csharp/Client/test/UnitTests/HubConnectionTests.ConnectionLifecycle.cs +++ b/src/SignalR/clients/csharp/Client/test/UnitTests/HubConnectionTests.ConnectionLifecycle.cs @@ -334,6 +334,26 @@ namespace Microsoft.AspNetCore.SignalR.Client.Tests }); } + [Fact] + public async Task StopAsyncOnInactiveConnectionDoesNotAffectNextStartAsync() + { + // Regression test: + // If there wasn't an active underlying connection, StopAsync would leave a CTS canceled which would cause the next StartAsync to fail + var testConnection = new TestConnection(); + await AsyncUsing(CreateHubConnection(testConnection), async connection => + { + Assert.Equal(HubConnectionState.Disconnected, connection.State); + + await connection.StopAsync().OrTimeout(); + Assert.False(testConnection.Disposed.IsCompleted); + Assert.Equal(HubConnectionState.Disconnected, connection.State); + + await connection.StartAsync().OrTimeout(); + Assert.True(testConnection.Started.IsCompleted); + Assert.Equal(HubConnectionState.Connected, connection.State); + }); + } + [Fact] public async Task CompletingTheTransportSideMarksConnectionAsClosed() {