简体   繁体   中英

SignalR Mapping Users to Connections Implementation

In SignalR ' Mapping Users to connections ' they have a pretty good implementation for mapping users to connections using Dictionary<T, HashSet<string>> however, I can't see the point of this portion of code in the Add method:

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

1) What's the point of adding an element to the local variable connections just before ending the method?

2) What's the point of having lock inside a 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);
                    }
                }
            }
        }
    }
}

1) connections is a local variable, but actually is a reference to an object, the SAME object that was added to the *_connections* dictionary. So even when it seems to be only a "local variable" it's actually a reference to a managed object that won't be disposed at the end of the method because it is referenced in the dictionary.

2) I'm not sure if this is really necessary, but the outer "lock (_connection)" will lock the whole dictionary, and the lock (connection) will lock only the current hashset.

The add is important to add a new connectionId for an existing user.

  1. User1 creates a connection (conn1). You create a new entry in the Dictonary with User1, {Conn1}
  2. User1 creates another connection, so you retrieve the existing connections by userId and add it, it becomes User1, {Conn1, Conn2}

I'm not sure why you'd need to lock it twice.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM