这些枚举/开始枚举队列吗?

时间:2013-06-25 10:07:39

标签: c# multithreading enumeration

我有一个可以从不同线程访问的静态队列。

Queue有一个实现的包装器,可以在添加/删除/设置时正确锁定。 还有一种方法可以锁定并返回Queue的副本,但这会产生一个新的可枚举,这有点浪费,所以我只想在必要的时候调用它。

我不想不必要地复制队列,但如果在我枚举的时候队列被更改,枚举就可以抛出异常。

枚举时是否存在抛出异常的可能性(由于上述原因):

  • QueueWrapper.InnerQueue.Any()(清空)
  • QueueWrapper.InnerQueue.FirstOrDefault(o => o.Something)
  • QueueWrapper.InnerQueue.Except(element)

我应该将QueueWrapper.InnerQueue替换为QueueWrapper.GetQueueCopy()

2 个答案:

答案 0 :(得分:0)

只有在更改基础集合时才会抛出枚举。 LINQ运算符(在您的情况下为AnyFirstOrDefaultExcept)不会更改集合,因此它们不会抛出。

答案 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并行枚举仅运行一次