如何使自定义线程安全通用列表返回C#中的整个列表?

我是一个线程菜鸟,我试图在C#(.NET 3.5 SP1)中编写一个自定义线程安全通用列表类。 我已经阅读了为什么线程安全集合如此困难? 。 在查看了课程的要求之后,我想我只需要安全地添加到列表中并返回列表。 该示例显示了我想要的所有内容,除了它缺少返回列表方法,因此我编写了自己的公共方法,如下所示:

更新:根据给出的建议,我已经审查了我的要求,因此将课程简化为如下:

public sealed class ThreadSafeList { private readonly IList list = new List(); private readonly object lockable = new object(); public void Add(T t) { lock (lockable) { list.Add(t); } } public IList GetSnapshot() { IList result; lock (lockable) { result = new List(list); } return result; } } 

同意@jrista。 您需要解决一个语义问题,为什么它被称为Translate() ? 意图是什么?

A – 当前代码 – 返回内部列表的只读包装

 return new ReadOnlyCollection(list); 

如果原始列表被更改,如果另一个线程在列表上进行迭代,则仍然存在线程问题。 只要你意识到这一点,这不是一个大问题。

B – 只读副本。

 return new List(list).AsReadOnly(); 

此列表没有线程问题,因为没有任何内容修改新列表。 唯一的引用是由ReadOnlyCollection包装器。

C – 正常(可写)副本

 return new List(list); 

返回一个新列表,调用者可以在不影响原始列表的情况下对列表执行所需操作,对原始列表的更改不会影响此列表。


如果另一个消费者抓取该列表的副本然后修改他们的副本,这是否重要? 消费者是否需要查看列表的更改? 你只需要一个线程安全的枚举器吗?

 public IEnumerator ThreadSafeEnumerator() { List copy; lock(lockable) copy = new List(list); foreach (var value in copy) yield return value; } 

根据我的经验,你必须在线程安全方面使用你的大脑,而不是依赖于这些解决方案。 简而言之,它取决于列表的接收者将使用它做什么。

Translate()方法看起来正确。 当您使用Translate / AddRange时,使用锁定可防止其他人添加或修改您的列表。

我认为您的IsReadyOnly属性可能存在问题。 在内部读取/写入属性时使用锁定。 但也有一个没有锁定的公共吸气剂。 线程1可能会调用MarkAsReadOnly,而第二个线程在查看IsReadOnly时可能仍会出错。 我会使用普通属性来锁定getter或使用volatile bool字段。

您可以使用SynchronizedCollection。

http://msdn.microsoft.com/en-us/library/ms668265.aspx