1

次の条件を持つ複数のスレッドを同期する方法を見つけようとしています。

  • スレッドには次の 2 種類があります。
    1. 循環計算を行うために無限ループを実行する単一の「循環」スレッド
    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
    }
}
4

1 に答える 1

4

ReaderWriterLockSlimが必要なようです。循環スレッドは「ライター」であり、他のスレッドは「リーダー」です。

于 2013-11-07T15:55:48.787 に答える