web-dev-qa-db-ja.com

セマフォの状態を確認する方法

Semaphoreの状態をチェックして、シグナルが送信されているかどうかを確認したいと思います(したがって、tがシグナルされている場合は、解放できます)。これどうやってするの?

EDIT1:

2つのスレッドがあります。1つはセマフォを待機し、もう1つはSemaphoreを解放する必要があります。問題は、最初のスレッドが待機していないときに、2番目のスレッドがRelease()を数回呼び出す可能性があることです。したがって、2番目のスレッドはRelease()を呼び出すとエラーが発生するかどうかを検出する必要があります(セマフォを待機している人がいない場合にセマフォを解放しようとするとエラーが発生します)。これどうやってするの?私はこれを行うためにフラグを使用できることを知っていますが、それは醜いです。より良い方法はありますか?

18
mans

Semaphoreを呼び出し、パラメータとしてタイムアウト値0を渡すことで、WaitOneが通知されているかどうかを確認できます。これにより、WaitOneがすぐに戻り、セマフォが通知されたかどうかを示すtrueまたはfalseの値が返されます。もちろん、これによりセマフォの状態が変化し、使用が煩雑になる可能性があります。

このトリックが役に立たないもう1つの理由は、少なくとも1つのカウントが使用可能な場合にセマフォが通知されると言われているためです。セマフォですべてのカウントが利用可能になったことを知りたいようです。 Semaphoreクラスにはその正確な能力はありません。 Releaseからの戻り値を使用してカウントを推測できますが、これによりセマフォの状態が変更されます。もちろん、セマフォに以前に使用可能なすべてのカウントがすでにある場合は、例外がスローされます。電話をかける。

必要なのは、スローしないリリース操作を備えたセマフォです。これはそれほど難しいことではありません。以下のTryReleaseメソッドは、カウントが使用可能になった場合はtrueを返し、セマフォがすでにmaximumCountにあった場合はfalseを返します。いずれにせよ、例外がスローされることはありません。

public class Semaphore
{
    private int count = 0;
    private int limit = 0;
    private object locker = new object();

    public Semaphore(int initialCount, int maximumCount)
    {
        count = initialCount;
        limit = maximumCount;
    }

    public void Wait()
    {
        lock (locker)
        {
            while (count == 0) 
            {
                Monitor.Wait(locker);
            }
            count--;
        }
    }

    public bool TryRelease()
    {
        lock (locker)
        {
            if (count < limit)
            {
                count++;
                Monitor.PulseAll(locker);
                return true;
            }
            return false;
        }
    }
}
15
Brian Gideon

Semaphore は、特定の時点で通知されているかどうかを確認する機能を提供していないため、他の同期オブジェクトが必要なようです。

セマフォを使用すると、たとえばWaitOne()/Release()メソッドを使用して、シグナル状態を待機するコードを自動的にトリガーできます。

新しい_.NET 4_クラス SemaphoreSlim を見ることができます。これは CurrentCount プロパティを公開します。おそらくそれを活用できます。

CurrentCount
SemaphoreSlimに入ることが許可されるスレッドの数を取得します。

編集:更新された質問のために更新されました

簡単な解決策として、semaphore.Release()をtry/catchでラップし、SemaphoreFullExceptionを処理できますが、期待どおりに機能しますか?

SemaphoreSlimを使用すると、次のようにCurrentCountを確認できます。

_ int maxCount = 5;
 SemaphoreSlim slim = new SemaphoreSlim(5, maxCount);            

 if (slim.CurrentCount == maxCount)
 {
    // generate error
 }
 else
 {
   slim.Release();
 }
_
7
sll

シグナリングを使用してセマフォを実装する方法は次のとおりです。スレッドセーフではないため、これ以外の状態を照会できることは意味がありません。

maxThreadsスロットを持つインスタンスを作成します。最初はすべて利用可能です:

var threadLimit = new Semaphore(maxThreads, maxThreads);

以下を使用して、スペアスロットを待機(ブロック)します(maxThreadsがすでに使用されている場合)。

threadLimit.WaitOne();

スロットを解放するには、以下を使用します。

threadLimit.Release(1);

完全な例があります ここ

4
TheCodeKing