I have a static ConcurrentDictionary
in a static
class. In the static constructor of the class, I call a private method via Task.Run
to indefinitely loop through the dictionary and remove items that have expired, i.e. a significant amount of time has passed since they were added and as such need to be removed (this is determined by by inspecting a property on each CustomItem
value of each item in the dictionary):
public static class ItemsHolder
{
public static ConcurrentDictionary<Guid, CustomItem> Items = new ConcurrentDictionary<Guid, CustomItem>();
// ...
static ItemsHolder
{
Task.Run(() => DeleteExpired());
}
private static async Task DeleteExpired()
{
while (true)
{
// check if dictionary is empty and if yes,
// await Task.Delay a bit, etc - omitted for brevity
foreach (var item in Items)
{
var guid = item.Key;
var customItem = item.Value;
if (customItem.ConditionToRemoveItemFromDictionaryHere)
{
var removeItem = Items.TryRemove(guid, out _);
// ...
}
}
}
}
}
In other parts of the code (outside of this class), items are being added to this dictionary and removed based on other conditions. Effectively DeleteExpired()
is there to clean out items that could not be removed from the dictionary (in other parts of the code, for XYZ reasons)
I see that DeleteExpired()
keeps popping up in my metrics in tools such as dotTrace in R# as occupying CPU time. I know that iterating through the concurrent dictionary while other threads might be adding/removing is lock-free and should be safe to do, but I'm not sure whether this is the most effective way of doing so. Is there a more effective/efficient way of doing so?