SignalR IHubContext和线程安全

本文关键字:安全 线程 IHubContext SignalR | 更新日期: 2023-09-27 18:05:53

在下面的代码示例中,我实现了一个SignalR Hub,它应该实现以下功能:

  • 客户端可以通过调用Hub的Subscribe方法来侦听Foo实例的变化,该方法带有一组id,这些id在内部被视为组名
  • 通过调用Unsubscribe
  • 来取消订阅
  • web应用程序的服务层可以通过调用OnFooChanged
  • 来通知订阅了相应id(组)的连接客户端发生了变化。

它是安全的使用一个单一的集线器上下文,还是我需要取它每次在OnFooChanged?我们也欢迎对其他方法的执行情况提供反馈。毕竟我是SignalR的新手。

[Export]
public class FooHub : Hub
{
  private static readonly Lazy<IHubContext> ctx = new Lazy<IHubContext>(
    () => GlobalHost.ConnectionManager.GetHubContext<FooHub>());
  #region Client Methods 
  public void Subscribe(int[] fooIds)
  {
    foreach(var fooId in fooIds)
      this.Groups.Add(this.Context.ConnectionId, fooId.ToString(CultureInfo.InvariantCulture));
  }
  public void Unsubscribe(int[] fooIds)
  {
    foreach (var fooId in fooIds)
      this.Groups.Remove(this.Context.ConnectionId, fooId.ToString(CultureInfo.InvariantCulture));
  }
  #endregion // Client Methods
  #region Server Methods
  /// <summary>
  /// Called from service layer when an instance of foo has changed
  /// </summary>
  public static void OnFooChanged(int id)
  {
    ctx.Value.Clients.Group(id.ToString(CultureInfo.InvariantCulture)).onFooChanged();
  }
  #endregion // Server Methods
}

SignalR IHubContext和线程安全

引自服务器广播教程:

只获取一次上下文有两个原因:获取上下文是一个代价高昂的操作,而且只获取一次确保发送到客户端的消息的预期顺序是保留。

所以,换句话说:使用Lazy单例是安全的,也是推荐的方法。如果每次要向客户机发送消息时都要获得一个新的上下文,那么可能会出现消息以不同于预期的顺序发送的风险。

我不知道为什么你可能需要定期获得一个新的上下文。