【发布时间】:2010-10-18 01:43:38
【问题描述】:
我在 ASP.NET 中有一个生产者-消费者场景。我设计了一个Producer 类,一个Consumer 类和一个用于保存共享对象并负责生产者和消费者之间通信的类,我们称之为Mediator。因为我在启动时(在父对象中)分叉了执行路径,一个线程会调用Producer.Start(),而另一个线程会调用Consumer.Start(),所以我需要将Mediator 的引用传递给Producer 和Consumer (通过Constructor)。 Mediator 是一个智能类,它将优化许多事情,比如它的内部队列的长度,但现在将其视为循环阻塞队列。 Producer 会将新对象入队 到Mediator,直到队列已满,然后Producer 将阻塞。 Consumer dequeues 对象从 Mediator 直到队列中没有任何内容。对于线程之间的信令,我在Mediator 类中实现了两个方法:Wait() 和Pulse()。代码是这样的:
Class Mediator
{
private object _locker = new object();
public void Wait()
{
lock(_locker)
Monitor.Wait(_locker);
}
public void Pulse()
{
lock(_locker)
Monitor.Pulse(_locker);
}
}
// This way threads are signaling:
Class Consumer
{
object x;
if (Mediator.TryDequeue(out x))
// Do something
else
Mediator.Wait();
}
在 Mediator 内部,我每次 Enqueued 或 Dequeued 使用 this.Pulse(),这样等待的线程就会收到信号并继续工作。
但我遇到了死锁,因为我从未使用过这种设计来发送信号线程,所以我不确定设计有问题还是我在其他地方做错了什么?
谢谢
【问题讨论】:
-
为什么每次出队时都要调用 Pulse(从而让生产者重新获得锁)?通常消费者会消费直到没有剩余物品,然后才调用Wait而不是Pulse。
-
因为生产者正在从外部服务器接收数据,我不确定它们的速度和可用性。所以对于 QoS(服务质量),我提前缓冲了 5 分钟消费者的需求。
标签: c# asp.net multithreading