I need to make a simple class that tracks how many clients are listening to a specific item, will be referred to as building hence forth. I will have a timer running that will check which buildings are active and send updates to them. While this is occurring, the client will be able connect and disconnect. This means they will also be modifying the building list as time goes on.
To make sure that I don't have any concurrency issues, I decided to make a simple class that uses a ConcurrencyDictionary<TKey, TValue>
. I don't have a need of the class in the past and want to make sure it is being used correctly as the documentation seems to lack a bit for this class, mostly when it comes to updating values and the like.
/// <summary>
/// Tracks the buildings that are actively being listened to and the number of clients subscribed to the building
/// </summary>
public static class BuildingSubscriptionTracker
{
/// <summary>
/// A dictionary of building name and listening client count
/// </summary>
private static readonly ConcurrentDictionary<string, int> _buildingsSubscribedTo = new ConcurrentDictionary<string, int>();
/// <summary>
/// Get all the buildings that are actively being listened to by clients
/// </summary>
/// <returns>An <see cref="System.Collections.Generic.IEnumerable{T}"/> of string</returns>
public static IEnumerable<string> GetBuildings()
{
return _buildingsSubscribedTo.Keys;
}
/// <summary>
/// Get how many clients are listening to updates for this building
/// </summary>
/// <param name="buildingName">Name of building to get client listening count for</param>
/// <returns>A count of how many clients are listening to updates for this building. If the building is no longer being tracked, this will return 0</returns>
public static int GetActiveClientCountFor(string buildingName)
{
int clientCount;
if (_buildingsSubscribedTo.ContainsKey(buildingName))
if (_buildingsSubscribedTo.TryGetValue(buildingName, out clientCount))
return clientCount;
return 0;
}
/// <summary>
/// Increment the client count of the given building
/// </summary>
/// <param name="buildingName">Name of the building the client wants updates for</param>
public static void IncrementClientCountFor(string buildingName)
{
//If the building doesn't exist, add it and +1 the count
if (!_buildingsSubscribedTo.ContainsKey(buildingName))
_buildingsSubscribedTo.TryAdd(buildingName, 0);
int clientCount;
_buildingsSubscribedTo.TryGetValue(buildingName, out clientCount);
_buildingsSubscribedTo.TryUpdate(buildingName, clientCount++, clientCount);
}
/// <summary>
/// Decrements the client count of the given building
/// </summary>
/// <param name="buildingName">Name of the building the client wants updates for</param>
public static void DecrementClientCountFor(string buildingName)
{
//If the building doesn't exist, there isn't anything to do
if (_buildingsSubscribedTo.ContainsKey(buildingName))
{
int clientCount;
//Get how many clients are listening to building so we can properly update it
if (_buildingsSubscribedTo.TryGetValue(buildingName, out clientCount))
{
var newClientCount = clientCount--;
if (newClientCount < 1)
{
int unusedValue;
_buildingsSubscribedTo.TryRemove(buildingName, out unusedValue);
}
else
{
_buildingsSubscribedTo.TryUpdate(buildingName, newClientCount, clientCount);
}
}
}
}
}