【发布时间】:2010-10-22 02:37:58
【问题描述】:
这不是关于我可以或应该使用哪些不同的方法来以最佳方式利用队列,而是我所看到的对我来说毫无意义的事情。
void Runner() {
// member variable
queue = Queue.Synchronized(new Queue());
while (true) {
if (0 < queue.Count) {
queue.Dequeue();
}
}
}
这是在单个线程中运行的:
var t = new Thread(Runner);
t.IsBackground = true;
t.Start();
其他事件在其他地方“排队”。我所看到的情况是在一段时间内,Dequeue 实际上会抛出 InvalidOperationException,队列为空。这应该是不可能的,因为计数如何保证那里有东西,而且我很肯定没有其他东西是“出队”的。
问题:
- Enqueue 是否有可能在项目完全进入队列之前增加计数(无论这意味着什么......)?
- 线程是否有可能在 Dequeue 语句处以某种方式重新启动(过期、重置...),但在它已经删除一个项目之后立即?
编辑(澄清):
这些代码片段是实现后台帮助线程的 Wrapper 类的一部分。这里的Dequeue是唯一的Dequeue,所有的Enqueue/Dequeue都在Synchronized成员变量(queue)上。
【问题讨论】:
-
因为 Ryan 的回答......这是真正的代码还是只是一个简化的例子?如果它是真正的代码,您应该真正考虑更改循环 - 轮询队列而不是使读取器与写入器同步是一个糟糕的设计。您正在浪费数百万个处理器周期来加热房间。
-
这是一个解决问题的例子。那里有一个 Thread.Sleep ,处理器没有被锤击。我选择轮询过程而不是同步读取/写入器的原因是因为队列中几乎一直都有东西。在我们的后备箱中,虽然我添加了一个 AutoResetEvent 来玩。就像我在顶部所说的那样,我并不十分关心这里的实施。这种线程模型似乎存在真正的问题,无论是对还是错。
-
通过查看您的代码,您至少拥有主线程和您认为调用 Dequeue 的线程。为什么不命名你的线程,每次调用 Dequeue 时,用堆栈跟踪记录线程的名称。您可能会发现主线程中的某些东西的行为方式出乎您的意料。
-
您应该为此使用BlockingCollection,而不是同步队列。
标签: c# multithreading