我是否可以将Monitor.Pulse
和Monitor.Wait
与ReaderWriterLockSlim
结合使用?
我有一个类,我已经封装了对底层队列的多线程访问。为了排队,我获得了一个保护底层队列(以及其他几个对象)的锁,然后添加项目和Monitor.Pulse
锁定的对象,以表示已将某些内容添加到队列中。
public void Enqueue(ITask task)
{
lock (mutex)
{
underlying.Enqueue(task);
Monitor.Pulse(mutex);
}
}
在队列的另一端,我有一个后台线程,它会在消息到达队列时不断处理它们。当队列中没有项目时,它使用Monitor.Wait
,以避免不必要的轮询。 (我认为这是一个很好的设计,但任何火焰(在合理范围内)如果它们帮助我学习其他方面都是受欢迎的。)
private void DequeueForProcessing(object state)
{
while (true)
{
ITask task;
lock (mutex)
{
while (underlying.Count == 0)
{
Monitor.Wait(mutex);
}
task = underlying.Dequeue();
}
Process(task);
}
}
随着更多操作被添加到此类(要求对受保护的底层的只读访问权限),有人建议使用ReaderWriterLockSlim
。我之前从未使用过该类,并假设它可以提供一些性能优势,我不反对它,但只有我能保持脉冲/等待设计。
答案 0 :(得分:1)
不,基本上。它经过优化,可提供一些特定/常见方案。如果你超出这些情况,它将无法工作。如果您需要Pulse
等,请改用Monitor
。
答案 1 :(得分:0)
在玩了一下之后(在接受了Mark的挑战之后(我同意,我的改变并不完全是基本的))我想出了这个组合:
ReaderWriterLockSlim rwls;
AutoResetEvent are;
public void Enqueue(ITask task) {
rwls.EnterWriteLock();
try {
underlying.Enqueue(task);
if (underlying.Count == 1) {
are.Set();
}
} finally {
rwls.ExitWriteLock();
}
}
private void DequeueForProcessing(object state) {
while (true) {
ITask task;
rwls.EnterWriteLock();
try {
while (underlying.Count == 0) {
rwls.ExitWriteLock();
are.WaitOne();
rwls.EnterWriteLock();
}
task = underlying.Dequeue();
} finally {
rwls.ExitWriteLock();
}
Process(task);
}
}
对于我未经训练的眼睛,这似乎符合要求(虽然它确实有点丑陋),并且它与原始版本没有太大区别。