다음을 통해 공유


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) 호출하여 세마포 수를 최대값으로 늘려 세마포를 입력할 수 있는 세 가지 작업을 허용합니다. 세마포가 해제될 때마다 이전 세마포 수가 표시됩니다. 콘솔 메시지는 세마포 사용을 추적합니다. 출력을 더 쉽게 읽을 수 있도록 각 스레드에 대해 시뮬레이션된 작업 간격이 약간 증가합니다.

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.

설명

세마포는 로컬 세마포와 명명된 시스템 세마포의 두 가지 유형입니다. 로컬 세마포는 애플리케이션에 로컬이고, 시스템 세마포는 운영 체제 전체에 표시되며 프로세스 간 동기화에 적합합니다. Windows SemaphoreSlim 커널 세마포를 사용하지 않는 클래스에 대한 간단한 대안 Semaphore 입니다. 클래스와 Semaphore 달리 클래스는 SemaphoreSlim 명명된 시스템 세마포를 지원하지 않습니다. 로컬 세마포로만 사용할 수 있습니다. 클래스는 SemaphoreSlim 단일 앱 내의 동기화에 권장되는 세마포입니다.

애플리케이션에 로컬 리소스의 풀에 대 한 액세스를 제어 하는 간단한 세마포입니다. 세마포를 인스턴스화할 때 세마포를 동시에 입력할 수 있는 최대 스레드 수를 지정할 수 있습니다. 또한 세마포를 동시에 입력할 수 있는 초기 스레드 수를 지정합니다. 이렇게 하면 세마포의 수가 정의됩니다.

스레드가 세마포에 들어갈 때마다 수가 감소하고 스레드가 세마포를 해제할 때마다 증가합니다. 세마포를 입력하기 위해 스레드는 오버로드 중 Wait WaitAsync 하나를 호출합니다. 세마포를 해제하려면 오버로드 중 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 , WaitAsyncRelease 메서드 호출에 스레드 또는 작업 ID를 Wait적용하지 않습니다. 또한 생성자를 사용하여 개체 CurrentCount 를 인스턴스화하는 SemaphoreSlim 경우 SemaphoreSlim(Int32) 생성자가 설정한 값 이상으로 속성을 늘릴 수 있습니다. 프로그래머의 책임은 메서드 호출 또는 메서드 호출 Wait 과 적절히 결합되도록 하는 것입니다Release.WaitAsync

생성자

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)

SemaphoreSlim을 확인하면서 시간 제한을 지정하는 부호 있는 32비트 정수를 사용하여 현재 스레드가 CancellationToken에 진입할 수 있을 때까지 스레드를 차단합니다.

Wait(TimeSpan)

SemaphoreSlim으로 시간 제한을 지정하여 현재 스레드가 TimeSpan에 진입할 수 있을 때까지 스레드를 차단합니다.

Wait(TimeSpan, CancellationToken)

SemaphoreSlim을 확인하면서 시간 제한을 지정하는 TimeSpan을 사용하여 현재 스레드가 CancellationToken에 진입할 수 있을 때까지 스레드를 차단합니다.

WaitAsync()

SemaphoreSlim으로 전환될 때까지 비동기적으로 기다립니다.

WaitAsync(CancellationToken)

SemaphoreSlim을 관찰하는 동안 CancellationToken으로 전환될 때까지 비동기적으로 기다립니다.

WaitAsync(Int32)

32비트 부호 있는 정수를 사용하여 시간 간격을 측정하여 SemaphoreSlim으로 전환될 때까지 비동기적으로 기다립니다.

WaitAsync(Int32, CancellationToken)

SemaphoreSlim을 관찰하는 동안 32비트 부호 있는 정수를 사용하여 시간 간격을 측정하여 CancellationToken으로 전환될 때까지 비동기적으로 기다립니다.

WaitAsync(TimeSpan)

SemaphoreSlim을 사용하여 시간 간격을 측정하여 TimeSpan으로 전환될 때까지 비동기적으로 기다립니다.

WaitAsync(TimeSpan, CancellationToken)

SemaphoreSlim을 관찰하는 동안 TimeSpan을 사용하여 시간 간격을 측정하여 CancellationToken으로 전환될 때까지 비동기적으로 기다립니다.

적용 대상

스레드 보안

모든 공용 및 보호된 멤버 SemaphoreSlim 는 스레드로부터 안전하며 여러 스레드에서 동시에 사용될 수 있습니다. 단 Dispose(), 다른 모든 작업이 SemaphoreSlim 완료된 경우에만 사용해야 합니다.

추가 정보