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

ASP.NET Core 8中SignalR的UnsubscribeFromWatchlist方法未触发问题

ASP.NET Core 8 SignalR:UnsubscribeFromWatchlist方法无法触发服务端执行问题

在ASP.NET Core 8环境下的SignalR服务端定义了两个逻辑几乎一致的待调用方法,仅SubscribeToWatchlist方法在客户端调用时能触发服务端执行,UnsubscribeFromWatchlist方法却无法触发。

触发Unsubscribe方法时,Chrome开发者工具显示请求内容为{"arguments":[1],"invocationId":"7","target":"UnsubscribeFromWatchlist","type":1}{"type":7},说明客户端连接及请求均正常,但服务端的VS断点和Debug.WriteLine均无响应。

服务端代码

public async Task SubscribeToWatchlist(int watchlistType)
{
    int userId = int.Parse(Context.User.Identity.Name);
    string connectionId = Context.ConnectionId;

    if (_watchlistSubscriptions.TryAdd(Context.ConnectionId + watchlistType, new CancellationTokenSource()))
    {
        await _realtimeService.MonitorWatchlist(watchlistType, userId, connectionId, _watchlistSubscriptions[Context.ConnectionId + watchlistType].Token);
    }
}

public void UnsubscribeFromWatchlist(int watchlistType)
{
    int userId = int.Parse(Context.User.Identity.Name);
    string connectionId = Context.ConnectionId;

    //await Groups.RemoveFromGroupAsync(Context.ConnectionId, "watchlist-" + watchlistType);

    if (_watchlistSubscriptions.TryRemove(Context.ConnectionId + watchlistType, out var cts))
    {
        _realtimeService.StopMonitoringWatchlist(watchlistType, userId, connectionId, cts.Token);
        cts.Cancel();
        cts.Dispose();
    }
}

客户端JavaScript代码

async subscribeToWatchlist() {
  await this.connection.invoke("SubscribeToWatchlist", 1);
},

async unsubscribeFromWatchlist() {
  await this.connection.invoke("UnsubscribeFromWatchlist", 1);
},

可能的原因及解决方案

  • 方法返回值不符合SignalR要求:SignalR规定,客户端通过invoke调用的服务端方法必须返回Task或Task<T>类型。UnsubscribeFromWatchlist当前返回void,会导致SignalR无法正确处理异步调用的完成信号,进而出现服务端方法不触发的情况。修改方法返回类型为Task,即使没有异步操作,也返回Task.CompletedTask:

    public Task UnsubscribeFromWatchlist(int watchlistType)
    {
        int userId = int.Parse(Context.User.Identity.Name);
        string connectionId = Context.ConnectionId;
    
        if (_watchlistSubscriptions.TryRemove(Context.ConnectionId + watchlistType, out var cts))
        {
            _realtimeService.StopMonitoringWatchlist(watchlistType, userId, connectionId, cts.Token);
            cts.Cancel();
            cts.Dispose();
        }
        return Task.CompletedTask;
    }
    
  • 潜在异常未被捕获:如果Context.User.Identity.Name解析失败(比如用户身份信息丢失),void方法抛出的异常无法被SignalR捕获并反馈给客户端,会表现为服务端方法看似未触发。改为Task返回后,异常会被SignalR传递到客户端,可通过客户端的catch块排查问题:

    async unsubscribeFromWatchlist() {
      try {
        await this.connection.invoke("UnsubscribeFromWatchlist", 1);
      } catch (err) {
        console.error(err);
      }
    },
    
  • 同步操作阻塞线程:若_realtimeService.StopMonitoringWatchlist是耗时的同步阻塞方法,可能占用SignalR的处理线程,导致方法无法正常执行。可将该方法改为异步,或在异步线程中执行同步操作避免阻塞。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 12:17:02