C# AutoResetEvent-两个set调用不会很快发生';不能保证线程释放-为什么?
我正在阅读MSDN上的AutoResetEvent文档,下面的警告让我有点烦 “重要: 无法保证对Set方法的每次调用都会释放一个线程。如果两个调用距离太近,因此在释放线程之前发生第二个调用,则只释放一个线程。这就好像第二个调用没有发生一样。此外,如果在没有线程等待且AutoResetEvent已为sig的情况下调用Set但是,电话没有任何效果。” 但是这个警告基本上扼杀了使用这种线程同步技术的理由。例如,我有一个可以保存工作的列表。而且只有一家生产商会在名单上增加工作岗位。我有很多消费者(不止一个)在等着从名单中得到这份工作。。像这样的 制作人:C# AutoResetEvent-两个set调用不会很快发生';不能保证线程释放-为什么?,c#,warnings,msdn,autoresetevent,C#,Warnings,Msdn,Autoresetevent,我正在阅读MSDN上的AutoResetEvent文档,下面的警告让我有点烦 “重要: 无法保证对Set方法的每次调用都会释放一个线程。如果两个调用距离太近,因此在释放线程之前发生第二个调用,则只释放一个线程。这就好像第二个调用没有发生一样。此外,如果在没有线程等待且AutoResetEvent已为sig的情况下调用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中的警告感到困惑。这是一个有效的警告吗?即使警告不是真的并且设置为原子,为什么要在这里使用AutoResetEvent?假设您有一些生产者将3个事件排成一行,并且有一个消费者。在处理第二个作业后,使用者将阻止并永远不会处理第三个作业
对于这种类型的同步,我将使用。基本上,您需要多个生产者才能拥有写锁,但您不希望消费者在仅读取队列大小时长时间锁定生产者。即使警告不正确且设置为原子,您为什么要在此处使用AutoResetEvent?假设您有一些生产者将3个事件排成一行,并且有一个消费者。在处理第二个作业后,使用者将阻止并永远不会处理第三个作业
对于这种类型的同步,我将使用。基本上,您需要多个生产者才能拥有写锁,但您不希望消费者在仅读取队列大小时长时间锁定生产者。MSDN上的消息确实是有效的消息。内部发生的事情是这样的:
或者,我建议您查看.NET 4.0中引入的BCL的System.Collections.Concurrent命名空间中的BlockingCollection类,它完全执行您试图执行的操作MSDN上的消息确实是一条有效消息。内部发生的事情是这样的:
或者,我建议您查看.NET 4.0中引入的BCL的System.Collections.Concurrent命名空间中的BlockingCollection类,它完全执行您正在尝试执行的操作是的,此代码只能在意外情况下正常工作。不要发明这个轮子,谷歌“c#producer-consumer queue”搜索大量样本。我在搜索中发现的大多数producer-consumer都使用等待/信号方法。这种方法的问题在于,当我想让员工辞职时,我必须提交虚拟工作。但如果我可以使用事件,我就可以让工人等待两个事件。一个用于作业,另一个用于关闭。感觉更干净。是的,这个代码只能在意外情况下正常工作。不要发明这个轮子,谷歌“c#producer-consumer queue”搜索大量样本。我在搜索中发现的大多数producer-consumer都使用等待/信号方法。这种方法的问题在于,当我想让员工辞职时,我必须提交虚拟工作。但如果我可以使用事件,我就可以让工人等待两个事件。一个用于作业,另一个用于关闭。那感觉更干净。。