次の方法で共有


SemaphoreSlim クラス

定義

リソースまたはリソースのプールに同時にアクセスできるスレッドの数を制限する Semaphore の軽量版を表します。

public ref class SemaphoreSlim : IDisposable
public class SemaphoreSlim : IDisposable
[System.Runtime.InteropServices.ComVisible(false)]
public class SemaphoreSlim : IDisposable
type SemaphoreSlim = class
    interface IDisposable
[<System.Runtime.InteropServices.ComVisible(false)>]
type SemaphoreSlim = class
    interface IDisposable
Public Class SemaphoreSlim
Implements IDisposable
継承
SemaphoreSlim
属性
実装

次の例では、3 つのスレッドの最大数と 0 個のスレッドの初期カウントを持つセマフォを作成します。 この例では、セマフォを待機しているブロックを含む 5 つのタスクを開始します。 メイン スレッドは、オーバーロードを Release(Int32) 呼び出してセマフォの数を最大に増やします。これにより、3 つのタスクがセマフォに入ることができます。 セマフォが解放されるたびに、前のセマフォ数が表示されます。 コンソール メッセージはセマフォの使用を追跡します。 シミュレートされた作業間隔は、出力を読みやすくするために、スレッドごとにわずかに増加します。

using System;
using System.Threading;
using System.Threading.Tasks;

public class Example
{
    private static SemaphoreSlim semaphore;
    // A padding interval to make the output more orderly.
    private static int padding;

    public static void Main()
    {
        // Create the semaphore.
        semaphore = new SemaphoreSlim(0, 3);
        Console.WriteLine("{0} tasks can enter the semaphore.",
                          semaphore.CurrentCount);
        Task[] tasks = new Task[5];

        // Create and start five numbered tasks.
        for (int i = 0; i <= 4; i++)
        {
            tasks[i] = Task.Run(() =>
            {
                // Each task begins by requesting the semaphore.
                Console.WriteLine("Task {0} begins and waits for the semaphore.",
                                  Task.CurrentId);
                
                int semaphoreCount;
                semaphore.Wait();
                try
                {
                    Interlocked.Add(ref padding, 100);

                    Console.WriteLine("Task {0} enters the semaphore.", Task.CurrentId);

                    // The task just sleeps for 1+ seconds.
                    Thread.Sleep(1000 + padding);
                }
                finally {
                    semaphoreCount = semaphore.Release();
                }
                Console.WriteLine("Task {0} releases the semaphore; previous count: {1}.",
                                  Task.CurrentId, semaphoreCount);
            });
        }

        // Wait for half a second, to allow all the tasks to start and block.
        Thread.Sleep(500);

        // Restore the semaphore count to its maximum value.
        Console.Write("Main thread calls Release(3) --> ");
        semaphore.Release(3);
        Console.WriteLine("{0} tasks can enter the semaphore.",
                          semaphore.CurrentCount);
        // Main thread waits for the tasks to complete.
        Task.WaitAll(tasks);

        Console.WriteLine("Main thread exits.");
    }
}
// The example displays output like the following:
//       0 tasks can enter the semaphore.
//       Task 1 begins and waits for the semaphore.
//       Task 5 begins and waits for the semaphore.
//       Task 2 begins and waits for the semaphore.
//       Task 4 begins and waits for the semaphore.
//       Task 3 begins and waits for the semaphore.
//       Main thread calls Release(3) --> 3 tasks can enter the semaphore.
//       Task 4 enters the semaphore.
//       Task 1 enters the semaphore.
//       Task 3 enters the semaphore.
//       Task 4 releases the semaphore; previous count: 0.
//       Task 2 enters the semaphore.
//       Task 1 releases the semaphore; previous count: 0.
//       Task 3 releases the semaphore; previous count: 0.
//       Task 5 enters the semaphore.
//       Task 2 releases the semaphore; previous count: 1.
//       Task 5 releases the semaphore; previous count: 2.
//       Main thread exits.
Imports System.Threading
Imports System.Threading.Tasks

Module Example
   Private semaphore As SemaphoreSlim
    ' A padding interval to make the output more orderly.
    Private padding As Integer

   Public Sub Main()
      ' Create the semaphore.
      semaphore = New SemaphoreSlim(0, 3)
      Console.WriteLine("{0} tasks can enter the semaphore.",
                        semaphore.CurrentCount)
      Dim tasks(4) As Task

      ' Create and start five numbered tasks.
      For i As Integer = 0 To 4
         tasks(i) = Task.Run(
            Sub()
               ' Each task begins by requesting the semaphore.
               Console.WriteLine("Task {0} begins and waits for the semaphore.",
                              Task.CurrentId)
               semaphore.Wait()

               Interlocked.Add(padding, 100)

               Console.WriteLine("Task {0} enters the semaphore.", Task.CurrentId)

               ' The task just sleeps for 1+ seconds.
               Thread.Sleep(1000 + padding)

               Console.WriteLine("Task {0} releases the semaphore previous count: {1}.",
                                 Task.CurrentId, semaphore.Release())
            End Sub )
      Next

      ' Wait for half a second, to allow all the tasks to start and block.
      Thread.Sleep(500)

      ' Restore the semaphore count to its maximum value.
      Console.Write("Main thread calls Release(3) --> ")
      semaphore.Release(3)
      Console.WriteLine("{0} tasks can enter the semaphore.",
                        semaphore.CurrentCount)
      ' Main thread waits for the tasks to complete.
      Task.WaitAll(tasks)

      Console.WriteLine("Main thread exits.")
   End Sub
End Module
' The example displays output like the following:
'       0 tasks can enter the semaphore.
'       Task 1 begins and waits for the semaphore.
'       Task 5 begins and waits for the semaphore.
'       Task 2 begins and waits for the semaphore.
'       Task 4 begins and waits for the semaphore.
'       Task 3 begins and waits for the semaphore.
'       Main thread calls Release(3) --> 3 tasks can enter the semaphore.
'       Task 4 enters the semaphore.
'       Task 1 enters the semaphore.
'       Task 3 enters the semaphore.
'       Task 4 releases the semaphore; previous count: 0.
'       Task 2 enters the semaphore.
'       Task 1 releases the semaphore; previous count: 0.
'       Task 3 releases the semaphore; previous count: 0.
'       Task 5 enters the semaphore.
'       Task 2 releases the semaphore; previous count: 1.
'       Task 5 releases the semaphore; previous count: 2.
'       Main thread exits.

注釈

セマフォは、ローカル セマフォと名前付きシステム セマフォの 2 種類です。 ローカル セマフォはアプリケーションに対してローカルであり、システム セマフォはオペレーティング システム全体で表示され、プロセス間同期に適しています。 SemaphoreSlimは、Windows カーネル セマフォをSemaphore使用しない クラスの軽量な代替手段です。 Semaphoreクラスとは異なり、 SemaphoreSlim クラスは名前付きシステム セマフォをサポートしていません。 ローカル セマフォとしてのみ使用できます。 クラスは SemaphoreSlim 、1 つのアプリ内での同期に推奨されるセマフォです。

軽量セマフォは、アプリケーションに対してローカルなリソースのプールへのアクセスを制御します。 セマフォをインスタンス化するときに、セマフォに同時に入力できるスレッドの最大数を指定できます。 セマフォに同時に入力できるスレッドの初期数も指定します。 これにより、セマフォの数が定義されます。

カウントは、スレッドがセマフォに入るたびにデクリメントされ、スレッドがセマフォを解放するたびにインクリメントされます。 セマフォに入るために、スレッドは または WaitAsync オーバーロードのいずれかをWait呼び出します。 セマフォを解放するには、いずれかのオーバーロードを Release 呼び出します。 カウントが 0 に達すると、他のスレッドがセマフォを解放するまで、 Wait いずれかのメソッドの後続の呼び出しがブロックされます。 複数のスレッドがブロックされている場合、FIFO や LIFO など、スレッドがセマフォに入るタイミングを制御する順序は保証されません。

セマフォを使用してリソースを保護するコードの基本的な構造は次のとおりです。

' Enter semaphore by calling one of the Wait or WaitAsync methods.
SemaphoreSlim.Wait()
'
' Execute code protected by the semaphore.
'
SemaphoreSlim.Release()

すべてのスレッドがセマフォを解放すると、セマフォの作成時に指定された最大値がカウントされます。 セマフォのカウントは、 プロパティから CurrentCount 使用できます。

重要

クラスはSemaphoreSlim、および Release メソッドの呼び出しに対してWaitWaitAsyncスレッド ID またはタスク ID を適用しません。 さらに、コンストラクターを SemaphoreSlim(Int32) 使用してオブジェクトをインスタンス化 SemaphoreSlim する場合、 プロパティは CurrentCount コンストラクターによって設定された値を超えて増加する可能性があります。 または WaitAsync メソッドの呼び出しが、メソッドのWait呼び出しとRelease適切にペアになるようにするのはプログラマの責任です。

コンストラクター

SemaphoreSlim(Int32)

同時に許可される要求の初期数を指定して、SemaphoreSlim クラスの新しいインスタンスを初期化します。

SemaphoreSlim(Int32, Int32)

同時に許可される要求の初期数および最大数を指定して、SemaphoreSlim クラスの新しいインスタンスを初期化します。

プロパティ

AvailableWaitHandle

セマフォの待機に使用できる WaitHandle を返します。

CurrentCount

SemaphoreSlim オブジェクトに入る、残りのスレッド数を取得します。

メソッド

Dispose()

SemaphoreSlim クラスの現在のインスタンスによって使用されているすべてのリソースを解放します。

Dispose(Boolean)

SemaphoreSlim が使用しているアンマネージド リソースを解放します。オプションとして、マネージド リソースを解放することもできます。

Equals(Object)

指定されたオブジェクトが現在のオブジェクトと等しいかどうかを判断します。

(継承元 Object)
GetHashCode()

既定のハッシュ関数として機能します。

(継承元 Object)
GetType()

現在のインスタンスの Type を取得します。

(継承元 Object)
MemberwiseClone()

現在の Object の簡易コピーを作成します。

(継承元 Object)
Release()

SemaphoreSlim のオブジェクトを一度解放します。

Release(Int32)

指定された回数だけ、SemaphoreSlim オブジェクトを解放します。

ToString()

現在のオブジェクトを表す文字列を返します。

(継承元 Object)
Wait()

SemaphoreSlim に入れるようになるまで、現在のスレッドをブロックします。

Wait(CancellationToken)

SemaphoreSlim を観察すると同時に、CancellationToken に入れるようになるまで、現在のスレッドをブロックします。

Wait(Int32)

タイムアウト値を 32 ビット符号付き整数で指定して、SemaphoreSlim に入れるようになるまで、現在のスレッドをブロックします。

Wait(Int32, CancellationToken)

CancellationToken を観察すると同時に、タイムアウト値を 32 ビット符号付き整数で指定して、SemaphoreSlim に入れるようになるまで、現在のスレッドをブロックします。

Wait(TimeSpan)

TimeSpan を使用してタイムアウトを指定し、SemaphoreSlim に入れるようになるまで、現在のスレッドをブロックします。

Wait(TimeSpan, CancellationToken)

CancellationToken を観察すると同時に、タイムアウトを指定する TimeSpan を使用して、SemaphoreSlim に入れるようになるまで、現在のスレッドをブロックします。

WaitAsync()

SemaphoreSlim に移行するために非同期に待機します。

WaitAsync(CancellationToken)

CancellationToken を観察すると同時に、SemaphoreSlim に移行するために非同期に待機します。

WaitAsync(Int32)

32 ビット符号付き整数を使用して時間間隔を測定しながら、SemaphoreSlim に移行するために非同期に待機します。

WaitAsync(Int32, CancellationToken)

32 ビット符号付き整数を使用して時間間隔を測定しながら、CancellationToken を観察すると同時に、SemaphoreSlim に移行するために非同期に待機します。

WaitAsync(TimeSpan)

TimeSpan を使用して時間間隔を測定しながら、SemaphoreSlim に移行するために非同期に待機します。

WaitAsync(TimeSpan, CancellationToken)

SemaphoreSlim を使用して時間間隔を測定しながら、TimeSpan を観察すると同時に、CancellationToken に移行するために非同期に待機します。

適用対象

スレッド セーフ

のすべてのパブリック メンバーと保護されたメンバー SemaphoreSlim はスレッド セーフであり、複数の Dispose()スレッドから同時に使用できます。例外は、 に対 SemaphoreSlim する他のすべての操作が完了した場合にのみ使用する必要があります。

こちらもご覧ください