Skip to content

SignalR: Client awaiting long running server method leads to timeout on server-side #10257

@Apollo3zehn

Description

@Apollo3zehn

Describe the bug

I have a small setup where a C# client invokes a server method without parameters, simply waiting for an URL to return (both are v3.0.0-preview5). In my test setup, the server works on that zip file for 100s. During the call, the server prepares a zip file and returns a link to that file once finished. The server frequently sends status updates to the client.

With logs enabled on both sides and also using wireshark, I can see that the client sends pings regularly. However, if I get the source code right, the server does not process these pings due to the pending await call. The following happes:

  • after 30s, the server detects that no new message was received but continues without complains (I think this is intended)
  • after 60s, the server detects again that no frame was received and tries to abort the connection, but the invoked method continues to run. At this point, the client is not receiving status updates anymore from the server.
  • after 90s, the server detects again that no frame was received and tries to abort the connection, but the invoked method continues to run
  • after 100s, the invoked method returns, and the connection is actually aborted. OnDisconnectedAsync is called. On the client side, the error "A task was cancelled" appears.

I am not sure if this is by design (i.e. 'don't use async/await for very long running methods'), or if this is a bug, since the pings from the client are not processed.

If it is by design, what is the recommended alternative, when a client needs to wait for a long running methods?

To Reproduce

Hub content:

using Microsoft.AspNetCore.SignalR;
using System;
using System.Threading.Tasks;

namespace WebApplication1
{
    public class Broadcaster : Hub<IBroadcaster>
    {
        public Task<string> GetUrl()
        {
            int counter = 0;

            return Task.Run(async () =>
            {
                for (int i = 0; i < 100; i++)
                {
                    await Task.Delay(TimeSpan.FromSeconds(1));
                    await this.Clients.Client(this.Context.ConnectionId).SendProgress(counter, "Progress");
                    counter += 1;
                }

                return "url";
            });
        }
    }
}

Callback interface:

using System.Threading.Tasks;

namespace WebApplication1
{
    public interface IBroadcaster
    {
        Task SendProgress(double percent, string message);
    }
}

Client:

 _connection.On("SendProgress", (double percent, string message) =>
{
    Console.WriteLine($"{percent,3:0}%: {message}\n");
});

var url = await _connection.InvokeAsync<string>("GetUrl");

Expected behavior

I would expect that during an active connection where the client sends ping messages and server sends status updates, the connection is not cancelled.

Additional context

Include the output of dotnet --info

.NET Core SDK (gemäß "global.json"):
 Version:   3.0.100-preview5-011568
 Commit:    b487ff10aa

Laufzeitumgebung:
 OS Name:     Windows
 OS Version:  10.0.17763
 OS Platform: Windows
 RID:         win10-x64
 Base Path:   C:\Program Files\dotnet\sdk\3.0.100-preview5-011568\

Host (useful for support):
  Version: 3.0.0-preview5-27626-15
  Commit:  61f30f5a23

.NET Core SDKs installed:
  2.1.602 [C:\Program Files\dotnet\sdk]
  2.2.203 [C:\Program Files\dotnet\sdk]
  3.0.100-preview5-011568 [C:\Program Files\dotnet\sdk]

.NET Core runtimes installed:
  Microsoft.AspNetCore.All 2.1.9 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
  Microsoft.AspNetCore.All 2.2.4 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
  Microsoft.AspNetCore.App 2.1.9 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 2.2.4 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 3.0.0-preview5-19227-01 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.NETCore.App 2.1.9 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 2.2.4 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 3.0.0-preview5-27626-15 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.WindowsDesktop.App 3.0.0-preview5-27626-15 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]

Metadata

Metadata

Assignees

No one assigned

    Labels

    area-signalrIncludes: SignalR clients and servers

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions