I have code like this:
public ConcurrentDictionary<Guid, DeviceItem> deviceStatesCache = new ConcurrentDictionary<Guid, DeviceItem>();
private readonly object deviceStatesCacheLock = new object();
public void StoreDeviceStateInCache(Guid guid, DeviceItem deviceState)
{
bool added, removed, updated = false;
lock (deviceStatesCacheLock)
{
added = deviceStatesCache.TryAdd(guid, deviceState);
if (!added) {
removed = deviceStatesCache.TryRemove(guid, out var _);
if (removed)
{
updated = deviceStatesCache.TryAdd(guid, deviceState);
}
}
}
if (!updated)
throw new Exception("WTF: cannot update deviceStatesCache!");
}
private QueryDevicesResponse CreateQueryDevicesResponse()
{
var deviceItems = new List<DeviceItem>();
lock (deviceStatesCacheLock)
{
foreach (var item in deviceStatesCache)
{
deviceItems.Add(item.Value);
}
}
var response = new QueryDevicesResponse()
{
eventData = new QueryDevicesResponse.EventData()
{
devices = deviceItems
}
};
// response.eventSourceGuid = Guid.Empty.ToString();
return response;
}
(edit)
My lock
here is supposed to work in situations:
When another thread tries to get value when item is between remove and insert in
StoreDeviceStateInCache
method (and only this).When another thread started reading all items in
CreateQueryDevicesResponse()
method.
Can I simplify StoreDeviceStateInCache()
method a bit?
I know that AddOrUpdate method exists, but I can't find it helpful since I have to define additional methods and that would look less readable than my code.
looks like Michael Liu suggestion with deviceStatesCache[guid] = deviceState;
should be enough
Can I simplify CreateQueryDevicesResponse()
method a bit and read complete dictionary "atomically"?
(WTF stands for "What a Terrible Failure" kind of exception of course)