dotnet / aspnetcore

ASP.NET Core is a cross-platform .NET framework for building modern cloud-based web applications on Windows, Mac, or Linux.

Home Page:https://asp.net

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

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:

image

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:

  1. Start hub: src/SignalrHubLab > dotnet run
  2. Start client: src/SignalrHub.Client > dotnet run
  3. Press any key to trigger a connection start -> message sent -> connection closed
  4. Repeat 3
  5. Look for gaps in the logs in the Hub project similar to this:

image

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 use InvokeAsync.

Did not know, that! My bad, it seems to be consistently sending as expected now.