0

タイトルで申し訳ありませんが、私の問題を説明するのにこれ以上のものが見つかりませんでした...

アプリケーションで異なるスレッドを同期するのに苦労しています。これはおそらく、この問題に新しい見方を持っている人にとっては簡単な問題ですが、デッドロックについて何時間も調査した後、私の頭は爆発しており、同期メカニズムを作成する適切で安全な方法を見つけることができません:(

基本的に、複数のスレッドで実行される .Net プロセスがあります (すべてが 1 つのプロセスで実行されるため、IPC は必要ありません)。私は4つのスレッドを持っています:

  • 1 つのスレッド、それがSpecificThreadと呼ばれているとします。System.Timers.Timer定期的にコードを実行する があります。
  • 他に 3 つのスレッドがあり、それぞれが定期的にコードを実行するサービスを実行しています ( while (true)loop + Thread.Sleep(few ms))。

3 つのサービスはすべて同時に実行する必要があります。それらの同時実行がスレッドセーフであることを保証します。4 番目のスレッドであるSpecificThreadは、そのコードを定期的に実行する必要がありますが、他の 3 つのサービスの実行をブロックする必要があります。

基本的に、コードを定期的に実行するSpecificThreadがあります。SpecificThreadがそのコードを定期的に実行する場合、他のサービスがタスクを完了するまで待機する必要があります。他の 3 つのサービスがすべてタスクを完了したら、他の 3 つのサービスがブロックされている間、そのSpecificCodeを実行する必要があります。そのSpecificCodeが実行されると、他の 3 つのサービスがコードを再度実行できます。

SynchronizationContext4 つのスレッドすべてで共有されるオブジェクトの共有インスタンスがあります。これを使用してスレッドを同期できます。

public class SynchronizationContext
{
    public void StartService1()
    {
        ...
    }   
    public void StopService1()
    {
        ...
    }
    ...

    public void StartSpecificCode()
    {
        // Some sync here that wait until all 3 services completed their
        // respective tasks
    }
    public void NotifySpecificCodeCompleted()
    {
        // Some sync here that allows services 1 to 3 to execute again
    }
}

3 つのサービスの実行メカニズムは次のようになります。

// Only exits the loop when stopping the whole .Net process
while (myService.IsRunning)
{
    try
    {
        this.synchronizationContext.StartService1();

        // Do some job
    }
    finally
    {
        this.synchronizationContext.EndService1();

        // Avoids too much CPU usage for nothing in the loop
        Thread.Sleep(50);
    }
}

SpecificThread実行メカニズム:

// System.Timers.Timer that is instantiated on process start
if (this.timer != null)
{
    this.timer.Stop();
}

try
{
    // Must blocks until computation is possible
    this.synchronizationContext.StartSpecificCode();

    // Some job here that must execute while other 3
    // services are waiting
}
finally
{
    // Notify computation is done
    this.synchronizationContext.NotifySpecificCodeCompleted();

    // Starts timer again
    if (this.timer != null)
    {
        this.timer.Start();
    }
}

SpecificThread他の人が待っている間だけ実行する必要があるため、クリティカルセクションの使用方法がわかりません。Semaphore私は、 norを使用する方法を見つけられませんでしたAutoResetEvent(それらを使用すると、コードでデバッグが困難なデッドロックが発生しました)。ここでアイデアが不足しています...Interlocked静的メソッドが役立つでしょうか?

最後の言葉: 私のコードは .Net 3.5 で実行する必要があります。TPL もCountdownEventクラスも使用できません...

どんな助けでも大歓迎です!

4

1 に答える 1

1

ReaderWriterLockSlimまさにあなたを最も助けるツールのように聞こえます。各サービスがループの本体内で読み取りロックを解除するようにします。

while (true)
{
    try
    {
        lockObject.EnterReadLock();

        //Do stuff
    }
    finally
    {
        lockObject.ExitReadLock();
    }
}

次に、4 番目のスレッドは、その作業を実行したいときに書き込みロックに入ることができます。リーダー/ライター ロックの仕組みは、ライターがロックを保持していない限り、任意の数のリーダーがロックを保持でき、同時にロックを保持できるライターは 1 つだけです。これは、3 つのワーカーのいずれも他のワーカーをブロックしないことを意味しますが、4 番目のスレッドが実行されている場合、ワーカーはブロックされます。これはまさにあなたが望むものです。

于 2013-03-28T13:17:42.967 に答える