SignalR并发列表最佳实践

时间:2015-01-16 06:38:48

标签: c# signalr

我在c#MVC Web应用程序中使用SignalR。我想要一个当前表单身份验证用户的对象列表(UserDetail)。该对象应该包含UserId(表中的Pk)和ConnectionId(SignalR)。

今天我在集线器类中使用静态列表:

public static List<UserDetail> ConcurrentUsers = new List<UserDetail>();

并处理从列表中删除并在每个Hub事件中插入列表

public override Task OnDisconnected(bool stopCalled)
{
     if (ConcurrentUsers != null && ConcurrentUsers.Any(x => x.ConnectionId.Equals(Context.ConnectionId)))
          ConcurrentUsers.Remove(ConcurrentUsers.Find(x => x.ConnectionId.Equals(Context.ConnectionId)));
     return base.OnDisconnected(stopCalled);
}

public override Task OnConnected()
{
     IsUserAuthenticated();
     return base.OnConnected();
}

public override Task OnReconnected()
{
     IsUserAuthenticated();
     return base.OnReconnected();
}

private void IsUserAuthenticated()
{
     if (HttpContext.Current != null && HttpContext.Current.User != null &&  HttpContext.Current.User.Identity.IsAuthenticated)
     {
           var user = DalHelper.GetUserNoTracking(HttpContext.Current.User.Identity.Name);
           if (user == null)
           {
                 Clients.Caller.GoToLogin();
                 return null;
           }


           if (!ConcurrentUsers.Any(x => x.ConnectionId.Equals(Context.ConnectionId)))
           {
               UserDetail ud = new UserDetail { 
                  ConnectionId = Context.ConnectionId,
                  UserId = user.UserId,
               };
               ConcurrentUsers.Add(ud);
           }

      }
      return null;
}

当我想用他的数据更新用户时,让我们说他收到的新消息然后我可以浏览列表并查找该用户的所有connectionId并将消息推送给所有用户连接的用户客户端。

private static void FlushMessageToClient(Guid UserId, string Message)
{
    string[] cids = Hub.ConcurrentUsers.Where(x => x.UserId.Equals(UserId)).Select(x => x.ConnectionId).ToArray();
    foreach (string cid in cids)
    {
        Hub.Clients.Client(cid).messageReceived(Message);
    }
}

一切正常,直到网站运行一小时进出用户,它将开始收到错误:

  

System.NullReferenceException:未将对象引用设置为实例   一个对象。在Infra.ChatHub.b__16(UserDetail   x)at System.Linq.Enumerable.Any [TSource](IEnumerable 1 source, Func 2   谓词)在ChatHub.IsUserAuthenticated()

有更好的方法来编程吗?

2 个答案:

答案 0 :(得分:0)

如果您有关键索引,我会使用字典:

Dictionary<Guid, UserDetail > dictionary = new Dictionary<Guid, UserDetail >();

你可以这样做:

dictionary.Add(userId, userDetail);   
var detail = dictionary[userId];

关于您的错误,请在查询之前检查userId是否在列表中。

if (dictionary.ContainsKey(userId)) {}

答案 1 :(得分:0)

可以找到最佳选项 将SignalR用户映射到连接。

http://www.asp.net/signalr/overview/guide-to-the-api/mapping-users-to-connections