【问题标题】:Use LINQ ToDictionary with ConcurrentDictionary将 LINQ ToDictionary 与 ConcurrentDictionary 一起使用
【发布时间】:2013-10-01 20:50:50
【问题描述】:

我正在使用字典来收集多线程应用程序中的事件,当我添加事件时使用锁,而在搜索事件时不使用它。 每隔一小时左右,我就会对超过特定时间的事件进行清理。 非常简单,而且很有效。

我想移动到 ConcurrentDictionary 来移除锁,我想我只需要添加“Concurrent”并将 Add 更改为 TryAdd。 但是后来我遇到了 LINQ 只返回 ToDictionary 的错误。 我显然不能使用 LINQ,但我很想知道是否可以做些什么来保护它。 更重要的是,在迁移到 ConcurrentDictionry 之前,我还应该考虑其他什么吗?

public class messageResult
        {
            public Result result;
            public DateTime receivedTime;
        }


public Dictionary<Guid, messageResult> events = new Dictionary<Guid, messageResult>();


lock (events)
            {
                events = events.Where(p => p.Value.receivedTime >= t).ToDictionary(p => p.Key, p => p.Value);
            }

谢谢

【问题讨论】:

  • 你为什么不用System.Runtime.Caching.MemoryCache
  • "当我添加一个事件时使用锁,而当我搜索一个事件时不使用它"锁不能这样工作,你必须阅读时锁定以防止在阅读时发生写入。但是,您可以通过使用 ReaderWriterLockSlim 来做您想做的事情(允许多个读者和一个作者),这将使您有很多读者,当一个作者想要写时,他们都会停下来。
  • @L.B 感谢您的建议,但与我的共享 Dictionary 实例相比有什么优势?
  • @ScottChamberlain 我确定至少几秒钟内没有线程会读取我正在写入的值,这就是为什么我认为仅在写入时锁定就足够了。我错了吗?每次访问对象时我真的应该锁定吗?无论如何,我会检查您对 ReaderWriterLockSlim 的建议
  • @MattiaDurli 不是你需要锁在同一个key上,你需要锁在同一个bucket上。如果您尝试读取和写入字典内的同一个存储桶,可能会导致问题。

标签: .net multithreading concurrentdictionary


【解决方案1】:

看起来ToDictionary extension method 没有那么复杂,您可以创建自己的版本。

但请注意,ToDictionary 返回新对象,而您希望拥有一个字典并在线程之间共享它。

您不应该锁定可变变量(并且您还要更改对events 的实际引用),创建私有只读变量并将其用于锁定。

【讨论】:

【解决方案2】:

ToDictionary 返回一个新实例...与您的共享实例不同。

您想要修改您的共享实例并且应该编写执行此操作的代码:

foreach(var kvp in events.Where(...).ToList())
{
  var val = kvp.Value;
  events.TryRemove(kvp.Key out val);
}

【讨论】:

  • 是的,你是对的,它返回一个新实例,但由于它处于锁定状态,它应该可以工作(实际上它可以工作)。是我做错了还是表现不佳?
  • 顺便说一句,你的建议是使用ConcurrentDictionay,但是为什么要迭代你将它转换为List的元素,我不能直接遍历ConcurrentDictionary元素并TryRemove过期的元素吗?
猜你喜欢
  • 2015-12-05
  • 2018-05-17
  • 2010-12-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多