次の条件を持つ複数のスレッドを同期する方法を見つけようとしています。
- スレッドには次の 2 種類があります。
- 循環計算を行うために無限ループを実行する単一の「循環」スレッド
- メインスレッドによって開始されていない複数の存続期間の短いスレッド
- 循環スレッドには、各サイクル/ループ反復の間にスリープ期間があります
- 他のスレッドは、循環スレッドのサイクル間スリープ中に実行できます。
- アクティブなサイクル中に実行を試みる他のスレッドはブロックする必要があります
- 循環スレッドは、すでに実行中の他のすべてのスレッドが終了するまで待機します。
これが私がやろうと思っていたことの基本的な例です:
// 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
}
}