SemaphoreSlim 클래스

정의

리소스 또는 리소스 풀에 동시에 액세스할 수 있는 스레드 수를 제한하는 Semaphore 대신 사용할 수 있는 간단한 클래스를 나타냅니다.Represents a lightweight alternative to Semaphore that limits the number of threads that can access a resource or pool of resources concurrently.

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
특성
구현

예제

다음 예제에서는 최대 세 개의 스레드와 스레드 수가 0 개인 세마포를 만듭니다.The following example creates a semaphore with a maximum count of three threads and an initial count of zero threads. 이 예제에서는 세마포를 대기 하는 모든 블록의 5 개 작업을 시작 합니다.The example starts five tasks, all of which block waiting for the semaphore. 주 스레드는 Release(Int32) 오버 로드를 호출 하 여 세마포 수를 최대로 늘려 세 가지 작업을 통해 세마포에 진입할 수 있습니다.The main thread calls the Release(Int32) overload to increase the semaphore count to its maximum, which allows three tasks to enter the semaphore. 세마포가 해제 될 때마다 이전 세마포 수가 표시 됩니다.Each time the semaphore is released, the previous semaphore count is displayed. 콘솔 메시지는 세마포 사용을 추적 합니다.Console messages track semaphore use. 시뮬레이션 된 작업 간격은 각 스레드에 대해 약간 증가 하 여 출력을 보다 쉽게 읽을 수 있도록 합니다.The simulated work interval is increased slightly for each thread to make the output easier to read.

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.

설명

세마포는 로컬 세마포 및 명명 된 시스템 세마포에 대 한 두 가지 유형입니다.Semaphores are of two types: local semaphores and named system semaphores. 로컬 세마포는 응용 프로그램에 로컬로 적용 되며 시스템 세마포는 운영 체제 전체에서 표시 되 고 프로세스 간 동기화에 적합 합니다.Local semaphores are local to an application, system semaphores are visible throughout the operating system and are suitable for inter-process synchronization. SemaphoreSlim Semaphore Windows 커널 세마포를 사용 하지 않는 클래스에 대 한 간단한 대안입니다.The SemaphoreSlim is a lightweight alternative to the Semaphore class that doesn't use Windows kernel semaphores. 클래스와 달리 Semaphore 클래스는 SemaphoreSlim 명명 된 시스템 세마포를 지원 하지 않습니다.Unlike the Semaphore class, the SemaphoreSlim class doesn't support named system semaphores. 로컬 세마포에만 사용할 수 있습니다.You can use it as a local semaphore only. SemaphoreSlim클래스는 단일 응용 프로그램 내에서 동기화에 권장 되는 세마포입니다.The SemaphoreSlim class is the recommended semaphore for synchronization within a single app.

애플리케이션에 로컬 리소스의 풀에 대 한 액세스를 제어 하는 간단한 세마포입니다.A lightweight semaphore controls access to a pool of resources that is local to your application. 세마포를 인스턴스화할 때 세마포에 동시에 입력할 수 있는 최대 스레드 수를 지정할 수 있습니다.When you instantiate a semaphore, you can specify the maximum number of threads that can enter the semaphore concurrently. 또한 세마포에 동시에 입력할 수 있는 초기 스레드 수를 지정 합니다.You also specify the initial number of threads that can enter the semaphore concurrently. 세마포 수를 정의 합니다.This defines the semaphore's count.

이 수는 스레드가 세마포에 진입할 때마다 감소 하며, 스레드가 세마포를 해제할 때마다 증가 합니다.The count is decremented each time a thread enters the semaphore, and incremented each time a thread releases the semaphore. 세마포를 시작 하기 위해 스레드는 또는 오버 로드 중 하나를 호출 Wait WaitAsync 합니다.To enter the semaphore, a thread calls one of the Wait or WaitAsync overloads. 세마포를 해제 하기 위해이 메서드는 오버 로드 중 하나를 호출 Release 합니다.To release the semaphore, it calls one of the Release overloads. 개수가 0에 도달 하면 Wait 다른 스레드가 세마포를 해제할 때까지 메서드 중 하나에 대 한 후속 호출이 차단 됩니다.When the count reaches zero, subsequent calls to one of the Wait methods block until other threads release the semaphore. 여러 스레드가 차단 된 경우 스레드가 세마포에 진입할 때를 제어 하는 FIFO 또는 LIFO와 같은 보장 된 순서는 없습니다.If multiple threads are blocked, there is no guaranteed order, such as FIFO or LIFO, that controls when threads enter the semaphore.

세마포를 사용 하 여 리소스를 보호 하는 코드의 기본 구조는 다음과 같습니다.The basic structure for code that uses a semaphore to protect resources is:

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

모든 스레드가 세마포를 해제 한 경우 세마포가 생성 될 때 지정 된 최대값에 개수가 있습니다.When all threads have released the semaphore, the count is at the maximum value specified when the semaphore was created. 세마포의 개수는 속성에서 사용할 수 있습니다 CurrentCount .The semaphore's count is available from the CurrentCount property.

중요

SemaphoreSlim클래스는 Wait , WaitAsync 및 메서드에 대 한 호출에 스레드 또는 작업 id를 적용 하지 않습니다 Release .The SemaphoreSlim class doesn't enforce thread or task identity on calls to the Wait, WaitAsync, and Release methods. 또한 SemaphoreSlim(Int32) 생성자를 사용 하 여 개체를 인스턴스화하면 SemaphoreSlim CurrentCount 속성이 생성자에 의해 설정 된 값을 초과할 수 있습니다.In addition, if the SemaphoreSlim(Int32) constructor is used to instantiate the SemaphoreSlim object, the CurrentCount property can increase beyond the value set by the constructor. 또는 메서드에 대 한 호출이 Wait 메서드 호출과 적절 하 게 쌍을 이루어야 하는지 확인 하는 것은 프로그래머의 책임입니다 WaitAsync Release .It is the programmer's responsibility to ensure that calls to Wait or WaitAsync methods are appropriately paired with calls to Release methods.

생성자

SemaphoreSlim(Int32)

동시에 부여할 수 있는 초기 요청 수를 지정하여 SemaphoreSlim 클래스의 새 인스턴스를 초기화합니다.Initializes a new instance of the SemaphoreSlim class, specifying the initial number of requests that can be granted concurrently.

SemaphoreSlim(Int32, Int32)

동시에 부여할 수 있는 초기 및 최대 요청 수를 지정하여 SemaphoreSlim 클래스의 새 인스턴스를 초기화합니다.Initializes a new instance of the SemaphoreSlim class, specifying the initial and maximum number of requests that can be granted concurrently.

속성

AvailableWaitHandle

세마포에서 대기하는 데 사용할 수 있는 WaitHandle을(를) 반환합니다.Returns a WaitHandle that can be used to wait on the semaphore.

CurrentCount

SemaphoreSlim 개체에 들어갈 수 있는 남아 있는 스레드의 수를 가져옵니다.Gets the number of remaining threads that can enter the SemaphoreSlim object.

메서드

Dispose()

SemaphoreSlim 클래스의 현재 인스턴스에서 사용하는 모든 리소스를 해제합니다.Releases all resources used by the current instance of the SemaphoreSlim class.

Dispose(Boolean)

SemaphoreSlim에서 사용하는 관리되지 않는 리소스를 해제하고, 관리되는 리소스를 선택적으로 해제할 수 있습니다.Releases the unmanaged resources used by the SemaphoreSlim, and optionally releases the managed resources.

Equals(Object)

지정된 개체가 현재 개체와 같은지 확인합니다.Determines whether the specified object is equal to the current object.

(다음에서 상속됨 Object)
GetHashCode()

기본 해시 함수로 작동합니다.Serves as the default hash function.

(다음에서 상속됨 Object)
GetType()

현재 인스턴스의 Type을 가져옵니다.Gets the Type of the current instance.

(다음에서 상속됨 Object)
MemberwiseClone()

현재 Object의 단순 복사본을 만듭니다.Creates a shallow copy of the current Object.

(다음에서 상속됨 Object)
Release()

SemaphoreSlim 개체를 한 번 해제합니다.Releases the SemaphoreSlim object once.

Release(Int32)

SemaphoreSlim 개체를 지정된 횟수만큼 해제합니다.Releases the SemaphoreSlim object a specified number of times.

ToString()

현재 개체를 나타내는 문자열을 반환합니다.Returns a string that represents the current object.

(다음에서 상속됨 Object)
Wait()

현재 스레드가 SemaphoreSlim에 진입할 수 있을 때까지 스레드를 차단합니다.Blocks the current thread until it can enter the SemaphoreSlim.

Wait(CancellationToken)

SemaphoreSlim을 확인하면서 현재 스레드가 CancellationToken에 진입할 수 있을 때까지 스레드를 차단합니다.Blocks the current thread until it can enter the SemaphoreSlim, while observing a CancellationToken.

Wait(Int32)

시간 제한을 지정하는 부호 있는 32비트 정수를 사용하여 현재 스레드가 SemaphoreSlim에 진입할 수 있을 때까지 스레드를 차단합니다.Blocks the current thread until it can enter the SemaphoreSlim, using a 32-bit signed integer that specifies the timeout.

Wait(Int32, CancellationToken)

SemaphoreSlim을 확인하면서 시간 제한을 지정하는 부호 있는 32비트 정수를 사용하여 현재 스레드가 CancellationToken에 진입할 수 있을 때까지 스레드를 차단합니다.Blocks the current thread until it can enter the SemaphoreSlim, using a 32-bit signed integer that specifies the timeout, while observing a CancellationToken.

Wait(TimeSpan)

SemaphoreSlim으로 시간 제한을 지정하여 현재 스레드가 TimeSpan에 진입할 수 있을 때까지 스레드를 차단합니다.Blocks the current thread until it can enter the SemaphoreSlim, using a TimeSpan to specify the timeout.

Wait(TimeSpan, CancellationToken)

SemaphoreSlim을 확인하면서 시간 제한을 지정하는 TimeSpan을 사용하여 현재 스레드가 CancellationToken에 진입할 수 있을 때까지 스레드를 차단합니다.Blocks the current thread until it can enter the SemaphoreSlim, using a TimeSpan that specifies the timeout, while observing a CancellationToken.

WaitAsync()

SemaphoreSlim으로 전환될 때까지 비동기적으로 기다립니다.Asynchronously waits to enter the SemaphoreSlim.

WaitAsync(CancellationToken)

SemaphoreSlim을 관찰하는 동안 CancellationToken으로 전환될 때까지 비동기적으로 기다립니다.Asynchronously waits to enter the SemaphoreSlim, while observing a CancellationToken.

WaitAsync(Int32)

32비트 부호 있는 정수를 사용하여 시간 간격을 측정하여 SemaphoreSlim으로 전환될 때까지 비동기적으로 기다립니다.Asynchronously waits to enter the SemaphoreSlim, using a 32-bit signed integer to measure the time interval.

WaitAsync(Int32, CancellationToken)

SemaphoreSlim을 관찰하는 동안 32비트 부호 있는 정수를 사용하여 시간 간격을 측정하여 CancellationToken으로 전환될 때까지 비동기적으로 기다립니다.Asynchronously waits to enter the SemaphoreSlim, using a 32-bit signed integer to measure the time interval, while observing a CancellationToken.

WaitAsync(TimeSpan)

SemaphoreSlim을 사용하여 시간 간격을 측정하여 TimeSpan으로 전환될 때까지 비동기적으로 기다립니다.Asynchronously waits to enter the SemaphoreSlim, using a TimeSpan to measure the time interval.

WaitAsync(TimeSpan, CancellationToken)

SemaphoreSlim을 관찰하는 동안 TimeSpan을 사용하여 시간 간격을 측정하여 CancellationToken으로 전환될 때까지 비동기적으로 기다립니다.Asynchronously waits to enter the SemaphoreSlim, using a TimeSpan to measure the time interval, while observing a CancellationToken.

적용 대상

스레드 보안

의 모든 public 및 protected 멤버 SemaphoreSlim 는 스레드로부터 안전 하며를 제외 하 고 여러 스레드에서 동시에 사용할 수 있습니다. 단 Dispose() ,의 다른 모든 작업이 완료 된 경우에만 사용 해야 합니다 SemaphoreSlim .All public and protected members of SemaphoreSlim are thread-safe and may be used concurrently from multiple threads, with the exception of Dispose(), which must be used only when all other operations on the SemaphoreSlim have completed.

추가 정보