我有一个可以从不同线程访问的静态队列。
Queue有一个实现的包装器,可以在添加/删除/设置时正确锁定。 还有一种方法可以锁定并返回Queue的副本,但这会产生一个新的可枚举,这有点浪费,所以我只想在必要的时候调用它。
我不想不必要地复制队列,但如果在我枚举的时候队列被更改,枚举就可以抛出异常。
枚举时是否存在抛出异常的可能性(由于上述原因):
QueueWrapper.InnerQueue.Any()
(清空)QueueWrapper.InnerQueue.FirstOrDefault(o => o.Something)
QueueWrapper.InnerQueue.Except(element)
我应该将QueueWrapper.InnerQueue
替换为QueueWrapper.GetQueueCopy()
?
答案 0 :(得分:0)
只有在更改基础集合时才会抛出枚举。 LINQ运算符(在您的情况下为Any
,FirstOrDefault
和Except
)不会更改集合,因此它们不会抛出。
答案 1 :(得分:0)
您显示的所有操作确实会枚举队列,因此在这些操作期间您将无法更改它,因此它不是线程安全的(这取决于您锁定队列更新操作的方式)。
如果您需要保护枚举,那么您需要更高级别的锁定。
为了达到最佳效果,为了避免在已有读卡器时锁定新读卡器,您可以使用 ReaderWriterLockSlim (http://msdn.microsoft.com/library/system.threading.readerwriterlockslim.aspx)。
您将拥有以下代码:
ReaderWriterLockSlim rwls = new ReaderWriterLockSlim();
...
rwls.EnterReadLock();
try
{
// some enumeration
}
finally
{
rwls.ExitReadLock();
}
...
rwls.EnterWriteLock();
try
{
// some bulk update
}
finally
{
rwls.ExitWriteLock();
}
通过这种方式,您可以在任何给定时间 n并行枚举但仅运行一次。