SignalR Stop connection immediately after Send won't always deliver the Send
jenspettersson opened this issue · comments
Is there an existing issue for this?
- I have searched the existing issues
Describe the bug
Not sure this is a recommended way of doing this, but we have a .net service that executes very infrequently and on some occasion it needs to connect to a SignalR hub and invoke a method. Due to the infrequent use, we are starting a new connection, invoking the method and then closing the connection immediately, illustrated by a simplified sample that can reproduce our problem:
var hubConnection = new HubConnectionBuilder()
.WithUrl("http://localhost:5067/hub")
.Build();
await hubConnection.StartAsync();
var message = Guid.NewGuid().ToString().Substring(0, 8);
await hubConnection.SendAsync("TestMethod", message);
await hubConnection.StopAsync();
This works, most of the time, but not every time. Sometimes the hub doesn't receive the invokation request at all, only the connection/disconnection, illustrated by this screenshot from the sample repo I'll include:
It's very random, and thus hard to reproduce.
This happens in our production code where the invocations are a lot less frequent than in the reproduce repository. And as I said, it's really random.
The thing is, by adding a:
await Task.Delay(1);
between the SendAsync
and StopAsync
it doesn't miss anything (at least that's what I think based on my not-very-scientific-way-of-reproducing this).
We can of course try to register our signalr client as a singleton with a shared connection that always are alive, but I've always belived that when the SendAsync
task was done, the message was sent to the server, but now it seems like it's not fully sent and the StopAsync
might prevent the message from arriving.
Expected Behavior
When the SendAsync
task is done, the message has been delivered to the server and we can safely call StopAsync
on the connection.
Steps To Reproduce
A super simple solution with two projects that sometimes reproduces this:
https://github.com/jenspettersson/signalr-debug
To reproduce
Using a terminal/command line:
- Start hub:
src/SignalrHubLab
>dotnet run
- Start client:
src/SignalrHub.Client
>dotnet run
- Press any key to trigger a connection start -> message sent -> connection closed
- Repeat
3
- Look for gaps in the logs in the Hub project similar to this:
Exceptions (if any)
No response
.NET Version
6.0.106
Anything else?
No response
SendAsync
is fire and forget, there is no guarantee that the message ever reached the server. If you want to make sure the message reaches the server use InvokeAsync
.
SendAsync
is fire and forget, there is no guarantee that the message ever reached the server. If you want to make sure the message reaches the server useInvokeAsync
.
Did not know, that! My bad, it seems to be consistently sending as expected now.