我在MSDN上阅读的AutoResetEvent文档和以下警告有点困扰我。AutoResetEvent - 快速调用两个set不会保证线程的释放 - 为什么?
“重要提示: 没有保证的设置方法每次调用会释放一个线程如果两个呼叫靠得太近,所以。第二次调用发生在一个线程被释放之前,只有一个线程被释放,就好像第二次调用没有发生一样,并且如果在没有线程在等待并且AutoResetEvent已经被发送信号时调用Set,那么调用没有效果。“
但是这个警告基本上杀死了这样一个线程同步技术的原因。例如,我有一个可以保存工作的清单。而且只有一个生产者会将作业添加到列表中。我有消费者(不止一个),等待获得从列表中选择作业..这样的事情..
监制:
void AddJob(Job j)
{
lock(qLock)
{
jobQ.Enqueue(j);
}
newJobEvent.Set(); // newJobEvent is AutoResetEvent
}
消费者
void Run()
{
while(canRun)
{
newJobEvent.WaitOne();
IJob job = null;
lock(qLock)
{
job = jobQ.Dequeue();
}
// process job
}
}
如果上面的警告是真实的,那么如果我很快排队两个工作,只有一个线程会拿起工作,不是吗?我是假设下集将是原子,那就是它具有以下功能:
- 设置事件
- 如果线程都在等待,挑一个线程来唤醒
- 重置事件
- 运行选定的线程。
所以我基本上对MSDN中的警告感到困惑。这是一个有效的警告吗?
是的,这个代码将只工作正确的意外。不要发明这个轮子,谷歌的“C#生产者消费者队列”大量的样品。 – 2012-02-29 05:24:21
我发现大多数生产者消费者搜索,使用等待/信号方法。这种方法的问题在于,当我想让工人辞职时,我不得不提交虚假工作。但是如果我可以使用事件,我可以让工作人员等待两个事件。一个工作和其他关闭。那感觉更清洁.. – cgcoder 2012-02-29 19:49:44