You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ASP.NET Core SignalR Hub方法无法重复调用问题求助

ASP.NET Core SignalR 多次调用AddRow方法失效问题排查

问题场景

我在应用中使用ASP.NET Core SignalR,服务端代码如下:

public class Broadcast : Hub
{
     public async Task AddRow(Guid tableId)
     {
         RecordView newRow = _tableService.AddRow(tableId);

         await Clients.Group(tableId.ToString()).SendAsync("AddRow", newRow);
     }
}

客户端代码如下:

function addRow() {
    hubConnection.send("AddRow", useTables().tableId)
        .then(() => {
            console.log("AddRow Success!")
        })
        .catch((err) => {
            console.log("AddRow error: ", err)
        })
}

首次调用AddRow方法一切正常,但后续调用时该方法不再执行。我猜测这是因为服务器默认限制单客户端一次仅能调用一个方法,且服务器一直在等待任务完成。当我设置MaximumParallelInvocationsPerClient = 2后,该方法可被调用两次,但第三次调用又失效了。我不理解为何执行完await Clients.Group(tableId.ToString()).SendAsync("AddRow", newRow);后任务仍未被判定为完成。


可能原因及解决方案

1. 依赖服务存在同步阻塞

_tableService.AddRow(tableId)如果是同步执行的耗时操作(比如未异步化的数据库IO、文件读写),会占用Hub线程池资源,导致后续调用无法被处理。即使设置了并行调用上限,线程耗尽后依然会出现阻塞。

  • 改造AddRow为异步方法,用await调用避免同步阻塞:
    public async Task AddRow(Guid tableId)
    {
        RecordView newRow = await _tableService.AddRowAsync(tableId);
        await Clients.Group(tableId.ToString()).SendAsync("AddRow", newRow);
    }
    

2. 消息序列化或组内异常连接阻塞发送操作

SendAsync理论上在消息写入输出流后就会完成,但如果RecordView无法被正确序列化,或者组内存在未清理的异常连接,会导致底层异步操作无法完成:

  • 验证RecordView的序列化兼容性:避免循环引用、确保属性有公共getter、不使用SignalR不支持的类型(比如非可序列化的自定义类型);
  • 检查组内连接状态,在Hub方法中加入日志输出组内活跃连接数,排查异常连接:
    public async Task AddRow(Guid tableId)
    {
        var groupName = tableId.ToString();
        var clientCount = Clients.Group(groupName).Clients.Count();
        _logger.LogInformation("组{GroupName}内活跃连接数:{Count}", groupName, clientCount);
        
        RecordView newRow = _tableService.AddRow(tableId);
        await Clients.Group(groupName).SendAsync("AddRow", newRow);
    }
    

3. 客户端未正确处理调用上下文

如果客户端之前的send调用Promise未正确resolve/reject,或者连接在调用过程中意外断开重连,会导致后续调用被队列阻塞:

  • 检查客户端连接状态,确保每次调用addRow时hubConnection.state处于Connected状态;
  • 在客户端添加连接重连逻辑,确保重连后重新加入对应组。

4. 验证Hub方法的任务完成状态

在Hub方法中添加详细日志,定位任务卡在哪个环节:

private readonly ILogger<Broadcast> _logger;

public Broadcast(ILogger<Broadcast> logger, ITableService tableService)
{
    _logger = logger;
    _tableService = tableService;
}

public async Task AddRow(Guid tableId)
{
    _logger.LogInformation("开始执行AddRow,tableId: {TableId}", tableId);
    RecordView newRow = _tableService.AddRow(tableId);
    _logger.LogInformation("获取新行数据完成");
    
    await Clients.Group(tableId.ToString()).SendAsync("AddRow", newRow);
    _logger.LogInformation("发送消息到组完成");
}

内容的提问来源于stack exchange,提问作者Dmitry Rodin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 04:43:29