【问题标题】:Thread-safe replacement of ObservableCollection<T> in C# 4.0, with safe enumerationC# 4.0 中 ObservableCollection<T> 的线程安全替换,使用安全枚举
【发布时间】:2011-05-07 21:23:48
【问题描述】:

我的一个项目中有一个ObservableCollection&lt;T&gt;,我需要使访问线程安全。
特别是,我需要一个线程安全的枚举器。这意味着,在迭代集合期间(例如,在 LINQ 查询期间),没有人应该能够添加项目。

我注意到 .NET 4.0 命名空间 System.Collections.Concurrent 中的类。然而,它们似乎都不匹配。另外,在MSDN doc 中,我没有找到关于哪些访问实际上是 线程安全的段落。

某处是否存在我可以使用的现有线程安全集合,或者我必须自己实现它?

【问题讨论】:

  • 在迭代集合期间(例如,在 LINQ 查询期间),应该没有人能够添加项目。 如果有人尝试将项目添加到迭代时收集?它应该抛出异常吗?堵塞?成功但没有出现在迭代中?
  • @马克,谢谢你的想法。我希望它阻止更新。
  • 试试下面的链接,它提供了一个线程安全的解决方案,可以在任何线程上工作,并且可以通过多个 UI 线程绑定到:codeproject.com/Articles/64936/…

标签: c# collections concurrency thread-safety observablecollection


【解决方案1】:

请记住,如果您在 GetEnumerator 方法中取出锁,您可能会持有一个锁很长时间,在此期间没有人能够将对象添加到您的集合中:

foreach (var o in myCollection) {
    // Do something that takes 10 minutes
}

您还需要考虑如果同时发生多个迭代会发生什么。这意味着某种 MRSW 锁(多读单写),您可能必须自己实现。

听起来您实际上需要做的是迭代集合的快照:

foreach (var o in myCollection.ToArray()) {
    // ...
}

要正确执行此操作,您需要实现自己的 ICollection&lt;T&gt;,它在 ToArrayAdd 方法中取出锁

如果您更准确地给出您的要求或规范可能会有所帮助。

【讨论】:

  • 感谢thecoop 的启发性回答。我现在在从集合中读取时使用一个简单的 lock() 调用。这是一个相对较短的电话,我可以接受其他人被阻止的事实。很高兴知道您提到的选项!
【解决方案2】:

ObservableCollection 不是线程安全的。在它上面实现你自己的线程安全包装器。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-08-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-31
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多