2010-09-23 89 views
6

我想使用ThreadPool.RegisterWaitForSingleObject将一个计时器添加到一组线程。我创建了9个线程,并试图让他们每个人都有相同的操作机会,因为如果我只是将它们添加到线程池中,似乎会出现一些小小的匮乏。我也尝试执行手动重置事件,因为我希望所有9个线程在继续之前退出。正确的方式来实现ThreadPool.RegisterWaitForSingleObject

什么是确保线程池中的每个线程在运行时获得相同机会的最佳方式,因为我调用的函数有一个循环,并且似乎每个线程(或先运行的任何一个线程)都卡在它中其他人没有机会跑。

resetEvents = new ManualResetEvent[table_seats]; 
      //Spawn 9 threads 
      for (int i = 0; i < table_seats; i++) 
      { 
       resetEvents[i] = new ManualResetEvent(false); 
       //AutoResetEvent ev = new AutoResetEvent(false); 
       RegisteredWaitHandle handle = ThreadPool.RegisterWaitForSingleObject(autoEvent, ObserveSeat, (object)i, 100, false); 
      } 

      //wait for threads to exit 
      WaitHandle.WaitAll(resetEvents); 

但是,如果我使用resetEvents []或ev既不能正常工作也没关系。我能够实现这个还是我(可能)误解他们应该如何工作。

感谢,R.

回答

4

我不会为了这个目的使用RegisterWaitForSingleObject。由于您使用的是.NET v3.5,因此我要在此处描述的模式需要下载Reactive Extensions

首先,等待ThreadPool中的所有工作项目完成使用CountdownEvent类。这比使用多个ManualResetEvent实例更加优雅和可扩展。另外,WaitHandle.WaitAll方法限于64个句柄。

var finished = new CountdownEvent(1); 
for (int i = 0; i < table_seats; i++) 
{ 
    finished.AddCount(); 
    ThreadPool.QueueUserWorkItem(ObserveSeat); 
    (state) => 
    { 
     try 
     { 
     ObserveSeat(state); 
     } 
     finally 
     { 
     finished.Signal(); 
     } 
    }, i); 
} 
finished.Signal(); 
finished.Wait(); 

其次,你可以尝试后的多个循环迭代强制上下文切换调用Thread.Sleep(0)使当前线程的产量到另一个。如果你想要一个相当复杂的协调策略,那么使用Barrier类。将另一个参数添加到接受此同步机制的ObserveSeat函数中。您可以通过在上面的代码中的lambda表达式中捕获它来提供它。

public void ObserveSeat(object state, Barrier barrier) 
{ 
    barrier.AddParticipant(); 
    try 
    { 
    for (int i = 0; i < NUM_ITERATIONS; i++) 
    { 
     if (i % AMOUNT == 0) 
     { 
     // Let the other threads know we are done with this phase and wait 
     // for them to catch up. 
     barrier.SignalAndWait(); 
     } 
     // Perform your work here. 
    } 
    } 
    finally 
    { 
    barrier.RemoveParticipant(); 
    } 
} 

请注意,虽然这种方法肯定会阻止饥饿问题,但它可能会限制线程的吞吐量。调用SignalAndWait太多可能会导致大量不必要的上下文切换,但将其调用太少可能会导致大量不必要的等待。您可能需要调整AMOUNT以获得吞吐量和饥饿的最佳平衡。我怀疑可能有一个简单的方法来动态调整。

+1

谢谢,我还没有时间来测试这个,但感谢布赖恩的答案。 – flavour404 2010-09-27 19:23:45

相关问题