.NET线程同步

6
我计划使用自动重置事件句柄进行线程间通信。
EventWaitHandle handle = new EventWaitHandle(false, EventResetMode.AutoReset); 

我的生产者线程代码如下:

produceSomething(); 
handle.Set();

在消费者线程中,我需要每一分钟或当生产者调用Set方法时下载数据。
try 
{ 
    while(true) 
    { 
        handle.WaitOne(60000, false); 
        doSomething();  // Downloads data from Internet.
                        // Takes lot of time to complete it.
    } 
} 
catch(ThreadAbortException) 
{ 
    cleanup(); 
} 

我的问题是,如果消费者线程正在运行doSomething函数,而生产者调用了set函数,那么自动复位事件对象的状态会是什么?

我的要求是,一旦生产者调用set方法,我就必须从互联网上下载最新的数据。如果doSomething函数正在运行,当生产者调用set方法时,我必须中断它并再次调用。

2个回答

2
自动重置事件类似于一道门,在第一个线程通过后关闭。如果你在一个或多个线程等待时设置它,则一个线程会被唤醒,然后事件会被重置,其余的线程继续等待。
如果没有线程在等待时进行设置,则第一个调用handle.WaitOne的线程将不会等待,但它将导致事件被重置并继续执行。
摘自http://msdn.microsoft.com/en-us/library/system.threading.autoresetevent.aspx
调用Set信号AutoResetEvent以释放等待的线程。AutoResetEvent保持信号状态,直到单个等待线程被释放,然后自动返回非信号状态。如果没有线程在等待,状态将无限期地保持信号状态。
如果一个线程在AutoResetEvent处于信号状态时调用WaitOne,则该线程不会阻塞。AutoResetEvent立即释放线程并返回非信号状态。

1

在您的情况下自动重置事件的问题在于,“设置”它不支持排队。

也就是说,设置自动重置事件允许一个线程进入,如果在任何线程“消耗”您的事件之前再次设置它,则该“设置”将丢失。您可能希望两个线程能够进入并消费您所生产的任何内容,但实际上只有一个线程能够这样做。

在您的情况下,如果您的生产速度比消费速度快,则自动重置事件可能会误导。想象一下这种情况。

  • 生产者生产一个项目。
  • 消费者消耗该项目(重置事件并开始从互联网下载)
  • 制片人生产第二件物品。
  • 制片人生产第三件物品。
  • 生产停止。
  • 消费者消耗第二件物品(重新设置事件并重新开始下载)
  • 消费者永远不会消耗第三件物品,因为自动重置事件已被重置。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接