SignalR将用户映射到连接实现

时间:2014-02-21 01:53:38

标签: c# asp.net asp.net-mvc signalr

在SignalR'Mapping Users to connections'中,他们使用Dictionary<T, HashSet<string>>将用户映射到连接有一个非常好的实现但是,我无法在Add中看到这部分代码的重点方法:

 lock (connections)
 {
      connections.Add(connectionId);
 }

1)在结束方法之前,将一个元素添加到局部变量connections有什么意义?

2)lock内有lock是什么意思?

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace TraQ6.GeoTrack
{
    public class ConnectionMapping<T>
    {
        private readonly Dictionary<T, HashSet<string>> _connections =
            new Dictionary<T, HashSet<string>>();

        public int Count
        {
            get
            {
                return _connections.Count;
            }
        }

        public void Add(T key, string connectionId)
        {
            lock (_connections)
            {
                HashSet<string> connections;
                if (!_connections.TryGetValue(key, out connections))
                {
                    connections = new HashSet<string>();
                    _connections.Add(key, connections);
                }

                lock (connections) // here
                {
                    connections.Add(connectionId); // here
                } 
            }
        }

        public IEnumerable<string> GetConnections(T key)
        {
            HashSet<string> connections;
            if (_connections.TryGetValue(key, out connections))
            {
                return connections;
            }

            return Enumerable.Empty<string>();
        }

        public void Remove(T key, string connectionId)
        {
            lock (_connections)
            {
                HashSet<string> connections;
                if (!_connections.TryGetValue(key, out connections))
                {
                    return;
                }

                lock (connections)
                {
                    connections.Remove(connectionId);

                    if (connections.Count == 0)
                    {
                        _connections.Remove(key);
                    }
                }
            }
        }
    }
}

2 个答案:

答案 0 :(得分:1)

1) connections 是一个局部变量,但实际上是对象的引用,即添加到* _connections *字典的SAME对象。 因此,即使它看起来只是一个“局部变量”,它实际上也是对托管对象的引用,因为它在字典中被引用,所以它不会被放置在方法的末尾。

2)我不确定这是否真的有必要,但外部的“lock(_connection)”将锁定整个字典, lock(连接)将仅锁定当前的hashset

答案 1 :(得分:0)

添加对于为现有用户添加新的connectionId很重要。

  1. User1创建连接(conn1)。您可以使用User1, {Conn1}
  2. 在Dictonary中创建一个新条目
  3. User1创建另一个连接,因此您通过userId检索现有连接并添加它,它变为User1, {Conn1, Conn2}
  4. 我不确定为什么你需要锁定它两次。