我正在尝试找到一种方法来同步具有以下条件的多个线程:
- 有两种类型的线程:
- 单个“循环”线程执行无限循环以进行循环计算
- 主线程未启动多个短命线程
- 循环线程在每个循环/循环迭代之间有一个睡眠持续时间
- 允许其他线程在循环线程的循环间睡眠期间执行:
- 任何其他试图在活动周期中执行的线程都应该被阻止
- 循环线程将一直等待,直到所有其他已经在执行的线程完成
这是我正在考虑做的一个基本示例:
// Somewhere in the code:
ManualResetEvent manualResetEvent = new ManualResetEvent(true); // Allows external call
CountdownEvent countdownEvent = new CountdownEvent(1); // Can't AddCount a CountdownEvent with CurrentCount = 0
void ExternallyCalled()
{
manualResetEvent.WaitOne(); // Wait until CyclicCalculations is having its beauty sleep
countdownEvent.AddCount(); // Notify CyclicCalculations that it should wait for this method call to finish before starting the next cycle
Thread.Sleep(1000); // TODO: Replace with actual method logic
countdownEvent.Signal(); // Notify CyclicCalculations that this call is finished
}
void CyclicCalculations()
{
while (!stopCyclicCalculations)
{
manualResetEvent.Reset(); // Block all incoming calls to ExternallyCalled from this point forward
countdownEvent.Signal(); // Dirty workaround for the issue with AddCount and CurrentCount = 0
countdownEvent.Wait(); // Wait until all of the already executing calls to ExternallyCalled are finished
countdownEvent.Reset(); // Reset the CountdownEvent for next cycle.
Thread.Sleep(2000); // TODO: Replace with actual method logic
manualResetEvent.Set(); // Unblock all threads executing ExternallyCalled
Thread.Sleep(1000); // Inter-cycles delay
}
}
显然,这是行不通的。不能保证ExternallyCalled
在manualResetEvent.WaitOne();
主countdownEvent.AddCount();
线程被CountdownEvent
.
我想不出一个简单的方法来做我所追求的,经过长时间的搜索,我发现的几乎所有东西都与生产者/消费者同步有关,我不能在这里应用。
编辑:解决方案
根据接受的答案,这是如何做我想做的事情的要点:
// Somewhere in the code:
ReaderWriterLockSlim readerWriterLockSlim = new ReaderWriterLockSlim();
void ExternallyCalled()
{
readerWriterLockSlim.EnterReadLock();
Thread.Sleep(1000); // TODO: Replace with actual method logic
readerWriterLockSlim.ExitReadLock();
}
void CyclicCalculations()
{
while (!stopCyclicCalculations)
{
readerWriterLockSlim.EnterWriteLock();
Thread.Sleep(2000); // TODO: Replace with actual method logic
readerWriterLockSlim.ExitWriteLock();
Thread.Sleep(1000); // Inter-cycles delay
}
}