fla*_*404 6 c# multithreading visual-studio-2008
我试图使用ThreadPool.RegisterWaitForSingleObject将计时器添加到一组线程.我创建了9个线程,并且我试图给每个线程提供相同的操作机会,因为如果我只是将它们添加到线程池中,那么似乎会有一点饥饿.我也在尝试实现手动重置事件,因为我希望在继续之前退出所有9个线程.
什么是确保线程池中的每个线程获得相同的运行机会的最佳方法,因为我调用的函数有一个循环,似乎每个线程(或者先运行的任何一个)都卡在其中而其他线程都没有没机会跑.
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);
Run Code Online (Sandbox Code Playgroud)
但是,如果我使用resetEvents []或ev似乎无法正常工作并不重要.我能够实现这一点,还是我(可能)误解了它们应该如何工作.
谢谢,R.
我不会将其用于RegisterWaitForSingleObject此目的。我将在此处描述的模式需要下载响应式扩展,因为您使用的是 .NET v3.5。
首先,等待所有工作项从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();
Run Code Online (Sandbox Code Playgroud)
其次,您可以尝试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();
}
}
Run Code Online (Sandbox Code Playgroud)
请注意,虽然这种方法肯定可以防止饥饿问题,但它可能会限制线程的吞吐量。调用SignalAndWait太多可能会导致大量不必要的上下文切换,但调用太少可能会导致大量不必要的等待。您可能需要进行调整AMOUNT才能获得吞吐量和饥饿的最佳平衡。我怀疑可能有一种简单的方法可以动态地进行调整。