SignalR 调用有效但不 return 到客户端

SignalR call works but doesn't return to client

我正在使用 Blazor 构建 Web 应用程序,通过 SignalR 同步团队(我的域模型)。 (Blazor RC1 WebApp,core31 WebApi)

我的客户端有一个触发服务器将当前团队列表发送给客户端的调用。这个方法只有两行:

var currentTeams = await teamService.GetAllTeams().ConfigureAwait(false);
await SendTeamsToClient(currentTeams).ConfigureAwait(false);

那些工作 - SendTeamsToClient 获取列表并在客户端调用另一个 SignalR 方法 - 成功。对象被发送到客户端并在那里得到正确处理。

唯一的问题是:客户端调用从不 returns。客户端方法只有一行:

await connection.InvokeAsync(nameof(ServerHub.SubscribeToAndReceiveTeamsAsync));

而那个永远不会 returns。知道为什么吗?

我有一个变通方法,我将该方法称为“即发即弃”,但从长远来看,这确实不是一个可行的解决方案。

我还尝试让服务器将 SendTeamsToClient 调用为即发即弃,以防出现某种干扰。尽管如此,团队还是被发送了,但是最初在服务器上调用的集线器方法 returns 但从未在客户端上调用。

更新(MCVE 工作,我的项目不工作):

所以我尝试重现问题,但失败了。这个 MCVE 完美运行:

MCVE 前端,表示成功进入控制台的数字:

public async Task Ping()
{
    Console.WriteLine("Sending ping..."); // 1
    await c.InvokeAsync("Ping");
    Console.WriteLine("ping returned."); // 4
}

public Task Pong(string p)
{
    Console.WriteLine("Received pong: "+p); // 2+3
    Pongs.Add(p);
    StateHasChanged();
    return Task.CompletedTask;
}

MCVE 后端:

public async Task Ping()
{
    var pongs = new string[]
    {
        "Pong1",
        "Pong2"
    };
    await SendPongs(pongs).ConfigureAwait(false);
}

public async Task SendPongs(IEnumerable<string> pongs)
{
    foreach (var pong in pongs)
    {
        await Clients.Caller.Pong(pong).ConfigureAwait(false);
    }
}

实际项目前端:

public async Task SubscribeToAndReceiveTeamsAsync()
{
    Console.WriteLine("Frontend Hub triggering teams"); // This arrives
    await connection.InvokeAsync(nameof(ServerHub.SubscribeToAndReceiveTeamsAsync));
    Console.WriteLine("Frontend hub done triggering teams."); // This doesn't
}

public Task ReceiveTeam(Team team) // Works completely (teams arrive in view)
{
    Console.WriteLine("Frontend hub receiving team "+team.Name);
    Console.WriteLine($"Invoking event with {OnNewTeam?.GetInvocationList().Length} listener(s).");
    OnNewTeam?.Invoke(team);
    return Task.CompletedTask;
}

实际项目后端:

public async Task SubscribeToAndReceiveTeamsAsync()
{
    var currentTeams = await teamService.GetAllTeams().ConfigureAwait(false);
    Log(currentTeams.Count()); // This arrives with "2"
    await SendTeamsToClient(currentTeams).ConfigureAwait(false);
    Log("Server done"); // This arrives, therefore this method returns?
}

private async Task SendTeamsToClient(IEnumerable<Team> teams)
{
    foreach (var team in teams)
    {
        await Clients.Caller.ReceiveTeam(team).ConfigureAwait(false);
    }
}

不知道为什么一个行得通而另一个行不通。

快速更新:我用的是IIS还是self-hosted都无所谓。都不行。

更新 2

MCVE和实际项目都使用DI:

前端:

builder.Services.AddSingleton<HubConnection>(sp => new HubConnectionBuilder().WithUrl($"{builder.HostEnvironment.BaseAddress}signalr").WithAutomaticReconnect().Build());

后端:

app.UseEndpoints(endpoints =>
        {
            endpoints.MapRazorPages(); // <- Not in actual project
            endpoints.MapControllers();
            endpoints.MapFallbackToFile("index.html"); // <- Not in actual project
            endpoints.MapHub<MyHub>("/signalr");
        });

不过我确实添加了一个新方法,它也有同样的问题:

前端事件调用 await connection.InvokeAsync(nameof(ServerHub.SendChatMessage), message);

后端发送给其他客户端:

public Task SendChatMessage(string message)
{
    Clients.Others.ReceiveMessage(message).ConfigureAwait(false);
    return Task.CompletedTask;
} // Debugger says this returns successfully

其他人成功收到消息

调用者前端从不调用 returns。

所以我将我的项目升级到 .NET 5,现在它运行良好。不知道是关于框架还是 SignalR 更新,但我猜是点击了什么?