我一直在阅读有关syncroot元素但我无法在List类型中找到它。 那么如何使用System.Collections.Generic.List<>进行多线程同步呢?类型?
答案 0 :(得分:11)
为什么要锁定List<T>
而不是列表的特定实例?
通常建议锁定的最佳方法是锁定专门为此目的创建的私有对象。
private readonly object myListLock = new object();
// Everywhere you access myList
lock(myListLock)
{
// do stuff with myList
}
有关使用C#进行线程化的精彩指南,请参阅Joe Albahari的Free E-Book (Threading in C#)。
答案 1 :(得分:11)
你无法找到它的原因是因为它是explicitly removed。如果它确实是您想要做的,请使用SynchronizedCollection<T>
或创建专用同步对象。最好的方法(一般)是创建一个专用的同步对象,如Winston所示。
SyncRoot
属性的基本问题是它提供了一种错误的安全感 - 它只处理一组非常狭窄的情况。假设SyncRoot
上的锁定足够好,开发人员通常会忽略整个逻辑操作的同步。
您通常希望避免锁定类型(在这种情况下为List<T>
)。例如,如果您有两个类型的实例,或者另一个类型也使用List<T>
上的锁,那么它们都将竞争单个全局锁。实际上,您要实现的是单个对象的正确同步。
答案 2 :(得分:7)
您必须将通用列表转换为ICollection
,如下所示:
using System.Collection; // required for ICollection
using System.Collection.Generic;
List<int> myIntList = new List<int>();
lock (((ICollection)myIntList).SyncRoot)
{
// do your synchronized stuff here...
}
请记住,这只会同步访问通用列表的元素。它 不 同步对通用列表变量的访问权限,例如myIntList
。如果您在某个时候用新列表替换myIntList
,则使用SyncRoot
是不够的。在这种情况下,我建议创建一个可用于两种同步方案的特定同步对象。
答案 3 :(得分:2)
答案是肯定的,您可以使用列表实例作为同步对象:
{{1}}
因此,您不必使用SyncRoot属性。此外,documentation表示
对于底层商店不公开的集合, 预期的实现是返回当前实例。
即。在某些情况下,SyncRoot属性会返回集合对象本身。
另请阅读this answer有关SyncRoot的信息。
仅供参考:我从未在生产代码中看到过SyncRoot的用法。所以我建议你使用任何集合的实例作为同步对象而不是它的SyncRoot属性(只要集合是私有的)。