リソースまたはリソースのプールに同時にアクセスできるスレッドの数を制限できます。これはSemaphoreクラスの軽量な代替です。
public SemaphoreSlim ( int initialCount, int maxCount );SemaphoreSlim(Int32, Int32) - SemaphoreSlim コンストラクター (System.Threading) | Microsoft Learn
maxCountを省略するとInt32.MaxValueに設定されます。SemaphoreSlim - SemaphoreSlim.cs
initialCountがCurrentCountプロパティの初期値となります。そしてRelease()でSemaphoreSlimを解放したときに、maxCountを超えるとSemaphoreFullExceptionが投げられます。
SemaphoreSlim semaphore = new SemaphoreSlim(1, 3); int c1 = semaphore.Release(1); // 1 int c2 = semaphore.Release(1); // 2 semaphore.Release(); // SemaphoreFullException「指定されたカウントをセマフォに追加すると、カウントの最大値を超えます。」
要求の最大数を1として、Wait()と同一のスレッドでRelease()を呼ぶならば、lockやMonitorでも代用可能です。
型 | プロパティ | 内容 |
---|---|---|
int | CurrentCount | SemaphoreSlimオブジェクトに入ることができる、残りのスレッド数 |
WaitHandle | AvailableWaitHandle | セマフォの待機に使用できるWaitHandle |
SemaphoreSlimに入ることができるスレッド数で、Wait()で入ると減少し、Release()で解放すると増加します。
SemaphoreSlim semaphore = new SemaphoreSlim(3); // 初期値はコンストラクタで指定する int c1 = semaphore.CurrentCount; // 3 semaphore.Wait(); // 減算される int c2 = semaphore.CurrentCount; // 2 semaphore.Release(); // 加算される int c3 = semaphore.CurrentCount; // 3
CurrentCountが1以上となり、SemaphoreSlimに入れるまで現在のスレッドはブロックされます。この待ちをタイムアウトさせるにはWait(Int32)を、非同期に待たせるにはWaitAsync()を呼びます。
タイムアウトを指定しないWait()は、Wait(Timeout.Infinite)とするのと同じです。Wait - SemaphoreSlim.cs
public void Wait ();
SemaphoreSlimに入れたときはCurrentCountが1減算されます。
SemaphoreSlim semaphore = new SemaphoreSlim(1);
semaphore.Wait();
try
{
// クリティカル セクション
}
finally
{
semaphore.Release();
}
SemaphoreSlimに入れないときにスレッドをブロックせず、即座に結果を返すようにするにはタイムアウトを0とします。
SemaphoreSlim semaphore = new SemaphoreSlim(1);
if (semaphore.Wait(0))
{
try
{
}
finally
{
semaphore.Release();
}
}
else { } // SemaphoreSlimに入れなかった
SemaphoreSlimに入れるまで非同期に待たせられます。
public System.Threading.Tasks.Task WaitAsync ();
返されるTaskは、SemaphoreSlimに入ったときに完了します。
SemaphoreSlimを1つ解放できます。
public int Release ();
CurrentCountが1加算され、加算前の値が返されます。
SemaphoreSlimクラスを簡潔に記述できるようにしたクラスです。