Semaphore 類別

定義

限制可同時存取資源或資源池的執行緒數量。

public ref class Semaphore sealed : System::Threading::WaitHandle
public sealed class Semaphore : System.Threading.WaitHandle
[System.Runtime.InteropServices.ComVisible(false)]
public sealed class Semaphore : System.Threading.WaitHandle
type Semaphore = class
    inherit WaitHandle
[<System.Runtime.InteropServices.ComVisible(false)>]
type Semaphore = class
    inherit WaitHandle
Public NotInheritable Class Semaphore
Inherits WaitHandle
繼承
Semaphore
繼承
屬性

範例

以下程式碼範例建立一個最大計數為三、初始計數為零的信號量。 範例中起始五個執行緒,這些執行緒會阻塞等待信號板的出現。 主執行緒利用 Release(Int32) 方法超載將信號量數量提高到最大,允許三個執行緒進入信號量。 每個執行緒會使用該 Thread.Sleep 方法等待一秒,模擬工作,然後呼叫 Release() 方法過載以釋放信號量。 每次釋放臂板時,都會顯示前一次的臂板計數。 主控台訊息會追蹤臂板的使用。 模擬工作間隔會對每個線程略有增加,以使輸出更易閱讀。

using System;
using System.Threading;

public class Example
{
    // A semaphore that simulates a limited resource pool.
    //
    private static Semaphore _pool;

    // A padding interval to make the output more orderly.
    private static int _padding;

    public static void Main()
    {
        // Create a semaphore that can satisfy up to three
        // concurrent requests. Use an initial count of zero,
        // so that the entire semaphore count is initially
        // owned by the main program thread.
        //
        _pool = new Semaphore(initialCount: 0, maximumCount: 3);

        // Create and start five numbered threads. 
        //
        for(int i = 1; i <= 5; i++)
        {
            Thread t = new Thread(new ParameterizedThreadStart(Worker));

            // Start the thread, passing the number.
            //
            t.Start(i);
        }

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

        // The main thread starts out holding the entire
        // semaphore count. Calling Release(3) brings the 
        // semaphore count back to its maximum value, and
        // allows the waiting threads to enter the semaphore,
        // up to three at a time.
        //
        Console.WriteLine("Main thread calls Release(3).");
        _pool.Release(releaseCount: 3);

        Console.WriteLine("Main thread exits.");
    }

    private static void Worker(object num)
    {
        // Each worker thread begins by requesting the
        // semaphore.
        Console.WriteLine("Thread {0} begins " +
            "and waits for the semaphore.", num);
        _pool.WaitOne();

        // A padding interval to make the output more orderly.
        int padding = Interlocked.Add(ref _padding, 100);

        Console.WriteLine("Thread {0} enters the semaphore.", num);
        
        // The thread's "work" consists of sleeping for 
        // about a second. Each thread "works" a little 
        // longer, just to make the output more orderly.
        //
        Thread.Sleep(1000 + padding);

        Console.WriteLine("Thread {0} releases the semaphore.", num);
        Console.WriteLine("Thread {0} previous semaphore count: {1}",
            num, _pool.Release());
    }
}
Imports System.Threading

Public Class Example

    ' A semaphore that simulates a limited resource pool.
    '
    Private Shared _pool As Semaphore

    ' A padding interval to make the output more orderly.
    Private Shared _padding As Integer

    <MTAThread> _
    Public Shared Sub Main()
        ' Create a semaphore that can satisfy up to three
        ' concurrent requests. Use an initial count of zero,
        ' so that the entire semaphore count is initially
        ' owned by the main program thread.
        '
        _pool = New Semaphore(0, 3)

        ' Create and start five numbered threads. 
        '
        For i As Integer = 1 To 5
            Dim t As New Thread(New ParameterizedThreadStart(AddressOf Worker))
            'Dim t As New Thread(AddressOf Worker)

            ' Start the thread, passing the number.
            '
            t.Start(i)
        Next i

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

        ' The main thread starts out holding the entire
        ' semaphore count. Calling Release(3) brings the 
        ' semaphore count back to its maximum value, and
        ' allows the waiting threads to enter the semaphore,
        ' up to three at a time.
        '
        Console.WriteLine("Main thread calls Release(3).")
        _pool.Release(3)

        Console.WriteLine("Main thread exits.")
    End Sub

    Private Shared Sub Worker(ByVal num As Object)
        ' Each worker thread begins by requesting the
        ' semaphore.
        Console.WriteLine("Thread {0} begins " _
            & "and waits for the semaphore.", num)
        _pool.WaitOne()

        ' A padding interval to make the output more orderly.
        Dim padding As Integer = Interlocked.Add(_padding, 100)

        Console.WriteLine("Thread {0} enters the semaphore.", num)
        
        ' The thread's "work" consists of sleeping for 
        ' about a second. Each thread "works" a little 
        ' longer, just to make the output more orderly.
        '
        Thread.Sleep(1000 + padding)

        Console.WriteLine("Thread {0} releases the semaphore.", num)
        Console.WriteLine("Thread {0} previous semaphore count: {1}", _
            num, _
            _pool.Release())
    End Sub
End Class

備註

用這個 Semaphore 類別來控制資源池的存取。 執行緒透過呼叫 WaitOne 從類別繼承 WaitHandle 的方法進入信號量,並透過呼叫 Release 方法釋放信號量。

每當線程進入旗號時,信號量會減少;當線程釋放信號量時,數量會增加。 當計數為零時,後續請求會被阻塞,直到其他執行緒釋放信號量。 當所有執行緒都釋放了信號量後,計數值會回到信號量建立時指定的最大值。

沒有保證的順序,例如 FIFO 或 LIFO,阻塞的執行緒會進入信號量。

執行緒可以透過反覆呼叫該 WaitOne 方法多次進入信號量。 為了釋放部分或全部這些條目,執行緒可以多次呼叫無 Release() 參數方法的超載,或 Release(Int32) 呼叫指定要釋放的條目數量的方法過載。

Semaphore 類別不會在呼叫或 WaitOneRelease時強制執行緒身份。 程式設計師有責任確保執行緒不會過度釋放信號量。 例如,假設信號的最大計數為 2,而執行緒 A 和執行緒 B 都已經進入信號。 如果線程 B 中的程式設計錯誤導致呼叫 Release 兩次,這兩個呼叫都會成功。 號誌上的計數已滿,當執行緒 A 最終呼叫 Release 時,會拋出 SemaphoreFullException

臂板分為兩種類型:地方臂板和命名系統臂板。 如果你用一個接受名稱的建構子建立 Semaphore 物件,該物件會被關聯到該名稱的操作系統信號量。 命名的系統臂量遍布整個作業系統,可用來同步程序的活動。 你可以建立多個 Semaphore 代表相同命名系統信號量的物件,並利用此 OpenExisting 方法開啟現有的命名系統信號量。

本地臂板只存在於你的流程中。 它可以由進程中具有本地 Semaphore 對象引用的任何線程使用。 每個 Semaphore 物件都是獨立的本地信號量。

Caution

預設情況下,命名的信號量不限於創建它的使用者。 其他使用者可能能夠開啟並使用信號旗,包括多次取得信號旗卻不釋放來干擾信號量。 為了限制特定使用者的存取,你可以使用建構器超載,或 SemaphoreAcl 在建立命名旗號時傳遞 a SemaphoreSecurity 。 避免在可能有不受信任使用者執行程式碼的系統中使用無存取限制的命名信號量。

建構函式

名稱 Description
Semaphore(Int32, Int32, String, Boolean, SemaphoreSecurity)

初始化該類別的新實例 Semaphore ,指定初始條目數及最大並行條目數,可選擇性地指定系統信號量物件名稱,指定一個變數接收是否建立新系統信號量的值,並指定該系統信號量的安全存取控制。

Semaphore(Int32, Int32, String, Boolean)

初始化該類別的新實例 Semaphore ,指定初始條目數及最大並行條目數,並可選擇指定系統信號量物件名稱,並指定一個變數接收值,表示是否建立了新的系統信號量。

Semaphore(Int32, Int32, String, NamedWaitHandleOptions, Boolean)

初始化該類別的新實例 Semaphore ,指定初始條目數及最大並行條目數,可選擇性地指定系統信號量物件名稱及設定使用者範圍與會話範圍存取的選項,並指定一個變數接收值,表示是否建立了新的系統信號量。

Semaphore(Int32, Int32, String, NamedWaitHandleOptions)

初始化類別的新實例 Semaphore ,指定初始條目數及最大同時條目數,並可選擇性地指定系統信號量物件名稱及設定使用者範圍與會話範圍存取的選項。

Semaphore(Int32, Int32, String)

初始化該類別的新實例 Semaphore ,指定初始條目數與最大並行條目數,並可選擇指定系統信號量物件的名稱。

Semaphore(Int32, Int32)

初始化該類別的新實例 Semaphore ,指定初始條目數及最大並行條目數。

欄位

名稱 Description
WaitTimeout

表示操作 WaitAny(WaitHandle[], Int32, Boolean) 在任何等待句柄被通知前已逾時。 此欄位是常數。

(繼承來源 WaitHandle)

屬性

名稱 Description
Handle
已淘汰.
已淘汰.

取得或設定原生作業系統的 handle 。

(繼承來源 WaitHandle)
SafeWaitHandle

取得或設定原生作業系統的 handle 。

(繼承來源 WaitHandle)

方法

名稱 Description
Close()

釋放目前 WaitHandle所持有的所有資源。

(繼承來源 WaitHandle)
CreateObjRef(Type)

建立物件,其中包含產生用來與遠端物件通訊之 Proxy 所需的所有相關信息。

(繼承來源 MarshalByRefObject)
Dispose()

釋放目前類別實例 WaitHandle 所使用的所有資源。

(繼承來源 WaitHandle)
Dispose(Boolean)

當在衍生類別中被覆寫時,會釋放 所使用的 WaitHandle非管理資源,並可選擇性地釋放受管理資源。

(繼承來源 WaitHandle)
Equals(Object)

判斷指定的物件是否等於目前的物件。

(繼承來源 Object)
GetAccessControl()

取得命名系統信號量的存取控制安全性。

GetHashCode()

做為預設哈希函式。

(繼承來源 Object)
GetLifetimeService()
已淘汰.

擷取控制這個實例存留期原則的目前存留期服務物件。

(繼承來源 MarshalByRefObject)
GetType()

取得目前實例的 Type

(繼承來源 Object)
InitializeLifetimeService()
已淘汰.

取得存留期服務物件,以控制這個實例的存留期原則。

(繼承來源 MarshalByRefObject)
MemberwiseClone()

建立目前 Object的淺層複本。

(繼承來源 Object)
MemberwiseClone(Boolean)

建立一個 MarshalByRefObject 目前物件的淺層複製品。

(繼承來源 MarshalByRefObject)
OpenExisting(String, NamedWaitHandleOptions)

若已存在,則開啟指定的命名信號板。 若選項僅設定為目前使用者,物件的存取控制會被驗證為呼叫使用者。

OpenExisting(String, SemaphoreRights)

若已存在指定命名的旗號,則開啟所需的安全存取權限。

OpenExisting(String)

若已存在,則開啟指定的命名信號板。

Release()

退出信號板並返回先前的計數。

Release(Int32)

離開旗號指定次數並返回先前的計數。

SetAccessControl(SemaphoreSecurity)

設定命名系統信號量的存取控制安全性。

ToString()

傳回表示目前 物件的字串。

(繼承來源 Object)
TryOpenExisting(String, NamedWaitHandleOptions, Semaphore)

若已存在指定名稱的信號量,則開啟該名稱,並回傳一個表示操作是否成功的值。 若選項僅設定為目前使用者,物件的存取控制會被驗證為呼叫使用者。

TryOpenExisting(String, Semaphore)

若已存在指定名稱的信號量,則開啟該名稱,並回傳一個表示操作是否成功的值。

TryOpenExisting(String, SemaphoreRights, Semaphore)

若已存在指定命名的信號量,則以所需的安全存取開啟該信號,並回傳一個表示操作是否成功的值。

WaitOne()

阻擋目前執行緒,直到電流 WaitHandle 接收到訊號。

(繼承來源 WaitHandle)
WaitOne(Int32, Boolean)

在當前執行緒收到訊號前封鎖該執行緒 WaitHandle ,使用32位元有符號整數指定時間區間,並指定是否在等待前退出同步域。

(繼承來源 WaitHandle)
WaitOne(Int32)

在當前執行緒收到訊號前 WaitHandle ,會阻塞該執行緒,並使用 32 位元有號整數來指定以毫秒為單位的時間間隔。

(繼承來源 WaitHandle)
WaitOne(TimeSpan, Boolean)

阻塞目前執行緒直到目前實例收到訊號,並用 a TimeSpan 指定時間區間,並決定是否在等待前退出同步域。

(繼承來源 WaitHandle)
WaitOne(TimeSpan)

阻塞目前執行緒直到目前實例收到訊號,並使用 a TimeSpan 指定時間區間。

(繼承來源 WaitHandle)

明確介面實作

名稱 Description
IDisposable.Dispose()

此 API 支援此產品基礎結構,但無法直接用於程式碼之中。

釋放所有由 WaitHandle.

(繼承來源 WaitHandle)

擴充方法

名稱 Description
GetAccessControl(Semaphore)

回傳指定 semaphore的安全描述符。

GetSafeWaitHandle(WaitHandle)

取得原生作業系統等待句柄的安全句柄。

SetAccessControl(Semaphore, SemaphoreSecurity)

設定指定信號量的安全描述符。

SetSafeWaitHandle(WaitHandle, SafeWaitHandle)

為作業系統的原生等待句柄設定安全句柄。

適用於

執行緒安全性

此類型是安全線程。

另請參閱