C# 我可以简化我的ConcurrentDictionary吗;添加或更新";方法?

C# 我可以简化我的ConcurrentDictionary吗;添加或更新";方法?,c#,.net,concurrentdictionary,C#,.net,Concurrentdictionary,我有这样的代码: public ConcurrentDictionary<Guid, DeviceItem> deviceStatesCache = new ConcurrentDictionary<Guid, DeviceItem>(); private readonly object deviceStatesCacheLock = new object(); public void StoreDeviceStateInCache(Guid guid, DeviceI

我有这样的代码:

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;
}
公共ConcurrentDictionary设备statesCache=new ConcurrentDictionary(); 私有只读对象deviceStatesCacheLock=新对象(); 公用void存储设备状态缓存(Guid、DeviceItem设备状态) { bool添加、删除、更新=false; 锁(设备状态锁) { added=deviceStatesCache.TryAdd(guid,deviceState); 如果(!已添加){ removed=deviceStatesCache.TryRemove(guid,out var); 如果(已删除) { updated=deviceStatesCache.TryAdd(guid,deviceState); } } } 如果(!已更新) 抛出新异常(“WTF:无法更新deviceStatesCache!”); } 专用QueryDeviceResponse CreateQueryDeviceResponse()的 { var deviceItems=新列表(); 锁(设备状态锁) { foreach(deviceStatesCache中的var项目) { 添加设备项(项值); } } var response=newQueryDeviceResponse() { eventData=new QueryDeviceResponse.eventData() { 设备=设备项 } }; //response.eventSourceGuid=Guid.Empty.ToString(); 返回响应; } (编辑)

我的
应该在以下情况下工作:

  • 当另一个线程在
    StoreDeviceStateInCache
    方法中的项介于remove和insert之间时尝试获取值(并且仅此)

  • 当另一个线程开始读取
    createQueryDeviceResponse()方法中的所有项时

  • 我能稍微简化一下
    StoreDeviceStateInCache()
    方法吗?

    我知道存在AddOrUpdate方法,但我觉得它没有什么帮助,因为我必须定义其他方法,而这些方法看起来不如我的代码可读

    类似于
    deviceStatesCache[guid]=deviceState应该足够了

    我能稍微简化一下
    createQueryDeviceResponse()
    方法并“原子地”阅读完整的词典吗?


    (WTF代表“多么可怕的失败”当然是一种例外)

    如果我正确理解了您的代码,您希望在密钥不存在时添加字典条目,如果密钥存在,则替换字典条目

    您可以通过使用ConcurrentDictionary的索引器来实现这一点,而无需任何额外的锁定:

    deviceStatesCache[guid] = deviceState;
    

    您还可以使用ConcurrentDictionary类型的AddOrUpdate方法来实现这一点。像下面这样


    deviceStatesCache.AddOrUpdate(guid,deviceState,(键,值)=>deviceState)

    请准确解释您的操作应该执行什么操作,以及您的目标是什么类型的线程安全。简化代码的一种方法是用普通的
    字典替换
    ConcurrentDictionary
    。如果您必须锁定任何
    ConcurrentDictionary
    的成员,那么您必须锁定所有成员(否则它将不会是线程安全的)。在这种情况下,
    ConcurrentDictionary
    的所有优点都消失了,剩下的就是它的缺点(不方便的API和同步开销).你能解释一下我应该在你的例子中把什么输入到
    key
    value
    中吗?@Kamil:
    key
    value
    只是lambda参数的任意名称,在本例中其值是未使用的。当ConcurrentDictionary调用lambda时,它将分别传递
    guid
    的值和
    deviceStatesCache[guid]
    的现有值。