在AddOrUpdate方法中更新密钥对象

时间:2015-01-30 16:15:54

标签: c# .net-4.0 concurrentdictionary

我有一个测试课。

class Test
{
    public int Id { get; set; }
    public int Val { get; set; }
}

我想设置一个ConcurrentDictionary,其中int为Key,Test为值。

bool External = true;
ConcurrentDictionary<int, Test> data = new ConcurrentDictionary<int, Test>();

我想为这个字典编写AddorUpdate的Update部分,这样如果一个外部变量(比如External)为true,那么Test的那个实例的Val应该增加100但是如果bool为false那么它应该递减100.有人可以帮助我,我该怎么做。我只是不确定如何使用lambda访问字典中的Test实例。即使是lambda,我也可以进行方法调用吗?

1 个答案:

答案 0 :(得分:2)

类似的东西:

data.AddOrUpdate(key, test, (k, t) =>
{
    var newTest = new Test { Id = t.Id, Val = t.Val };
    if (External)
        newTest.Val += 100;
    else
        newTest.Val -= 100;

    return newTest;
});

示例中的bool External将在匿名方法中以闭包结尾,因此它会变得非常奇怪并产生意外结果。你想以某种方式解决这个问题。

修改

我对这种方法不满意。我建议您定期Dictionary<int, Test>并提取当前值并进行更新,所有内容均为ReaderWriterLockSlim以确保状态。

var key = ...;
var lock = new ReaderWriterLockSlim();

lock.EnterWriteLock();
try
{
    if (dict.ContainsKey(key))
    {
        // update without closures
        var test = dict[key];
        if (External)
            test.Val += 100;
        else
            test.Val -= 100;
    }
}
else
{
    // insert
    var test = new Test { ...initial state... };
    dict.Add(key, test);
}
finally
{
    lock.ExitWriteLock();
}

最后,请务必将External标记为volatile以创建内存屏障并阻止可能会为您提供过期值的优化。