Semaphore 建構函式
定義
重要
部分資訊涉及發行前產品,在發行之前可能會有大幅修改。 Microsoft 對此處提供的資訊,不做任何明確或隱含的瑕疵擔保。
初始化 Semaphore 類別的新執行個體。
多載
Semaphore(Int32, Int32) |
初始化 Semaphore 類別的新執行個體,以及指定並行項目的最大數目及選擇性地保留某些項目。 |
Semaphore(Int32, Int32, String) |
初始化 Semaphore 類別的新執行個體,然後指定初始項目數目與並行項目的最大數目,以及選擇性地指定系統旗號物件的名稱。 |
Semaphore(Int32, Int32, String, Boolean) |
初始化 Semaphore 類別的新執行個體,然後指定初始項目物件數目與並行項目的最大數目,選擇性地指定系統號誌物件的名稱,以及指定接收值的變數,指出是否已建立新的系統號誌。 |
Semaphore(Int32, Int32, String, Boolean, SemaphoreSecurity) |
初始化 Semaphore 類別的新執行個體,然後指定初始項目數目與並行項目的最大數目,選擇性地指定系統號誌物件的名稱,指定接收值的變數 (以指示是否已建立新的系統號誌),以及指定系統號誌的安全性存取控制。 |
Semaphore(Int32, Int32)
- 來源:
- Semaphore.cs
- 來源:
- Semaphore.cs
- 來源:
- Semaphore.cs
初始化 Semaphore 類別的新執行個體,以及指定並行項目的最大數目及選擇性地保留某些項目。
public:
Semaphore(int initialCount, int maximumCount);
public Semaphore (int initialCount, int maximumCount);
new System.Threading.Semaphore : int * int -> System.Threading.Semaphore
Public Sub New (initialCount As Integer, maximumCount As Integer)
參數
- initialCount
- Int32
可同時授與給號誌的初始要求數目。
- maximumCount
- Int32
可以同時授與之號誌要求的最大數目。
例外狀況
initialCount
大於 maximumCount
。
範例
下列範例會建立最大計數為3且初始計數為零的號誌。 此範例會啟動五個線程,這會封鎖等候號誌。 主線程會 Release(Int32) 使用 方法多載,將號誌計數增加到其最大值,讓三個線程進入號誌。 每個線程都會 Thread.Sleep 使用 方法來等候一秒,以模擬工作,然後呼叫 Release() 方法多載以釋放旗號。 每次放開號誌時,就會顯示先前的號誌計數。 主控台訊息會追蹤號誌使用。 仿真的時間間隔會針對每個線程稍微增加,讓輸出更容易閱讀。
#using <System.dll>
using namespace System;
using namespace System::Threading;
public ref class Example
{
private:
// A semaphore that simulates a limited resource pool.
//
static Semaphore^ _pool;
// A padding interval to make the output more orderly.
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 = gcnew Semaphore( 0,3 );
// Create and start five numbered threads.
//
for ( int i = 1; i <= 5; i++ )
{
Thread^ t = gcnew Thread(
gcnew 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( L"Main thread calls Release(3)." );
_pool->Release( 3 );
Console::WriteLine( L"Main thread exits." );
}
private:
static void Worker( Object^ num )
{
// Each worker thread begins by requesting the
// semaphore.
Console::WriteLine( L"Thread {0} begins and waits for the semaphore.", num );
_pool->WaitOne();
// A padding interval to make the output more orderly.
int padding = Interlocked::Add( _padding, 100 );
Console::WriteLine( L"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( L"Thread {0} releases the semaphore.", num );
Console::WriteLine( L"Thread {0} previous semaphore count: {1}",
num, _pool->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
備註
此建構函式會初始化未命名的號誌。 使用這類號誌實例的所有線程都必須具有 實例的參考。
如果 initialCount
小於 maximumCount
,則效果與目前線程呼叫 WaitOne (減 initialCount
) maximumCount
次相同。 如果您不想為建立號誌的線程保留任何專案,請使用 和initialCount
的相同數位maximumCount
。
另請參閱
適用於
Semaphore(Int32, Int32, String)
- 來源:
- Semaphore.cs
- 來源:
- Semaphore.cs
- 來源:
- Semaphore.cs
初始化 Semaphore 類別的新執行個體,然後指定初始項目數目與並行項目的最大數目,以及選擇性地指定系統旗號物件的名稱。
public:
Semaphore(int initialCount, int maximumCount, System::String ^ name);
public Semaphore (int initialCount, int maximumCount, string name);
public Semaphore (int initialCount, int maximumCount, string? name);
new System.Threading.Semaphore : int * int * string -> System.Threading.Semaphore
Public Sub New (initialCount As Integer, maximumCount As Integer, name As String)
參數
- initialCount
- Int32
可同時授與給號誌的初始要求數目。
- maximumCount
- Int32
可以同時授與之號誌要求的最大數目。
- name
- String
如果同步物件要與其他處理序共用,則為名稱;否則為 null
或空字串。 名稱區分大小寫。 (\) 保留反斜杠字元,而且只能用來指定命名空間。 如需命名空間的詳細資訊,請參閱一節。 視操作系統而定,名稱可能會有進一步的限制。 例如,在 Unix 作業系統上,排除命名空間之後的名稱必須是有效的檔名。
例外狀況
initialCount
大於 maximumCount
。
-或-
僅限 .NET Framework:name
的長度超過 MAX_PATH (260 個字元)。
name
無效。 這可能基於數種原因,其中包括可能由作業系統設定的一些限制,例如未知前置詞或無效字元。 請注意,名稱和通用前置詞 「Global\」 和 「Local\」 會區分大小寫。
-或-
發生一些其他錯誤。
HResult
屬性可提供詳細資訊。
僅限 Windows:name
已指定未知命名空間。 請參閱物件名稱 \(英文\) 以取得詳細資訊。
name
太長。 長度限制可能會取決於作業系統或設定。
具名信號已存在,並且具有存取控制安全性,而使用者沒有 FullControl。
無法建立具有所提供 name
的同步物件。 不同類型的同步物件可能具有相同名稱。
範例
下列程式代碼範例示範具名號誌的跨進程行為。 此範例會建立具名號誌,其計數上限為 5,初始計數為 5。 程式會對 方法進行三次呼叫 WaitOne 。 因此,如果您從兩個命令視窗執行編譯的範例,第二個複本會在第三次呼叫 WaitOne時封鎖 。 釋放程式第一個複本中的一或多個專案,以解除封鎖第二個複本。
#using <System.dll>
using namespace System;
using namespace System::Threading;
public ref class Example
{
public:
static void main()
{
// Create a Semaphore object that represents the named
// system semaphore "SemaphoreExample3". The semaphore has a
// maximum count of five. The initial count is also five.
// There is no point in using a smaller initial count,
// because the initial count is not used if this program
// doesn't create the named system semaphore, and with
// this method overload there is no way to tell. Thus, this
// program assumes that it is competing with other
// programs for the semaphore.
//
Semaphore^ sem = gcnew Semaphore( 5,5,L"SemaphoreExample3" );
// Attempt to enter the semaphore three times. If another
// copy of this program is already running, only the first
// two requests can be satisfied. The third blocks. Note
// that in a real application, timeouts should be used
// on the WaitOne calls, to avoid deadlocks.
//
sem->WaitOne();
Console::WriteLine( L"Entered the semaphore once." );
sem->WaitOne();
Console::WriteLine( L"Entered the semaphore twice." );
sem->WaitOne();
Console::WriteLine( L"Entered the semaphore three times." );
// The thread executing this program has entered the
// semaphore three times. If a second copy of the program
// is run, it will block until this program releases the
// semaphore at least once.
//
Console::WriteLine( L"Enter the number of times to call Release." );
int n;
if ( Int32::TryParse( Console::ReadLine(),n ) )
{
sem->Release( n );
}
int remaining = 3 - n;
if ( remaining > 0 )
{
Console::WriteLine( L"Press Enter to release the remaining "
L"count ({0}) and exit the program.", remaining );
Console::ReadLine();
sem->Release( remaining );
}
}
};
using System;
using System.Threading;
public class Example
{
public static void Main()
{
// Create a Semaphore object that represents the named
// system semaphore "SemaphoreExample3". The semaphore has a
// maximum count of five. The initial count is also five.
// There is no point in using a smaller initial count,
// because the initial count is not used if this program
// doesn't create the named system semaphore, and with
// this method overload there is no way to tell. Thus, this
// program assumes that it is competing with other
// programs for the semaphore.
//
Semaphore sem = new Semaphore(5, 5, "SemaphoreExample3");
// Attempt to enter the semaphore three times. If another
// copy of this program is already running, only the first
// two requests can be satisfied. The third blocks. Note
// that in a real application, timeouts should be used
// on the WaitOne calls, to avoid deadlocks.
//
sem.WaitOne();
Console.WriteLine("Entered the semaphore once.");
sem.WaitOne();
Console.WriteLine("Entered the semaphore twice.");
sem.WaitOne();
Console.WriteLine("Entered the semaphore three times.");
// The thread executing this program has entered the
// semaphore three times. If a second copy of the program
// is run, it will block until this program releases the
// semaphore at least once.
//
Console.WriteLine("Enter the number of times to call Release.");
int n;
if (int.TryParse(Console.ReadLine(), out n))
{
sem.Release(n);
}
int remaining = 3 - n;
if (remaining > 0)
{
Console.WriteLine("Press Enter to release the remaining " +
"count ({0}) and exit the program.", remaining);
Console.ReadLine();
sem.Release(remaining);
}
}
}
Imports System.Threading
Public Class Example
<MTAThread> _
Public Shared Sub Main()
' Create a Semaphore object that represents the named
' system semaphore "SemaphoreExample3". The semaphore has a
' maximum count of five. The initial count is also five.
' There is no point in using a smaller initial count,
' because the initial count is not used if this program
' doesn't create the named system semaphore, and with
' this method overload there is no way to tell. Thus, this
' program assumes that it is competing with other
' programs for the semaphore.
'
Dim sem As New Semaphore(5, 5, "SemaphoreExample3")
' Attempt to enter the semaphore three times. If another
' copy of this program is already running, only the first
' two requests can be satisfied. The third blocks. Note
' that in a real application, timeouts should be used
' on the WaitOne calls, to avoid deadlocks.
'
sem.WaitOne()
Console.WriteLine("Entered the semaphore once.")
sem.WaitOne()
Console.WriteLine("Entered the semaphore twice.")
sem.WaitOne()
Console.WriteLine("Entered the semaphore three times.")
' The thread executing this program has entered the
' semaphore three times. If a second copy of the program
' is run, it will block until this program releases the
' semaphore at least once.
'
Console.WriteLine("Enter the number of times to call Release.")
Dim n As Integer
If Integer.TryParse(Console.ReadLine(), n) Then
sem.Release(n)
End If
Dim remaining As Integer = 3 - n
If (remaining) > 0 Then
Console.WriteLine("Press Enter to release the remaining " _
& "count ({0}) and exit the program.", remaining)
Console.ReadLine()
sem.Release(remaining)
End If
End Sub
End Class
備註
這個建構函式會 Semaphore 初始化 對象,這個物件表示具名系統號誌。 您可以建立多個 Semaphore 物件,代表相同的具名系統號誌。
name
前面可能會加上 Global\
或 Local\
,以指定命名空間。
Global
指定命名空間時,同步處理物件可能會與系統上的任何進程共用。
Local
指定命名空間時,這也是未指定命名空間時的預設值,同步處理物件可能會與相同會話中的進程共用。 在 Windows 上,會話是登入工作階段,而服務通常會在不同的非互動式會話中執行。 在類似 Unix 的作業系統上,每個殼層都有自己的會話。 會話本機同步處理物件可能適用於在進程與父子關聯性之間同步處理,而它們全都在相同的會話中執行。 如需 Windows 上同步處理物件名稱的詳細資訊,請參閱 物件名稱。
如果 已提供 , name
且要求之型別的同步處理物件已存在於 命名空間中,則會使用現有的同步處理物件。 如果命名空間中已經有不同類型的同步處理物件, WaitHandleCannotBeOpenedException
則會擲回 。 否則,會建立新的同步處理物件。
如果具名系統號誌不存在,則會使用 和maximumCount
所initialCount
指定的初始計數和最大計數來建立。 如果具名系統號誌已經存在, initialCount
而且 maximumCount
未使用,雖然無效的值仍然會造成例外狀況。 如果您需要判斷是否已建立具名系統號誌,請改用建 Semaphore(Int32, Int32, String, Boolean) 構函式多載。
重要
當您使用此建構函式多載時,建議的做法是針對 和 maximumCount
指定相同的數位initialCount
。 如果 initialCount
小於 maximumCount
,而且會建立具名系統號誌,則效果會與目前線程呼叫 WaitOne (maximumCount
減 initialCount
號) 次相同。 不過,使用此建構函式多載,無法判斷是否已建立具名系統號誌。
如果您指定 null
或的 name
空字串,就會建立本機號誌,就像您已呼叫 Semaphore(Int32, Int32) 建構函式多載一樣。
因為具名號誌在整個操作系統中都是可見的,所以可用來協調跨進程界限的資源使用。
如果您想要找出具名系統號誌是否存在,請使用 OpenExisting 方法。 方法 OpenExisting 會嘗試開啟現有的具名號誌,並在系統號誌不存在時擲回例外狀況。
警告
根據預設,具名號誌不限於建立它的使用者。 其他使用者可能能夠開啟和使用號誌,包括藉由多次取得號誌來干擾號誌,而不會釋放旗號。 若要限制特定使用者的存取,您可以使用建構函式多載,或在 SemaphoreAcl 建立具名號誌時傳入 SemaphoreSecurity 。 避免在執行程式代碼的系統上使用具名號誌,而不受存取限制。
另請參閱
適用於
Semaphore(Int32, Int32, String, Boolean)
- 來源:
- Semaphore.cs
- 來源:
- Semaphore.cs
- 來源:
- Semaphore.cs
初始化 Semaphore 類別的新執行個體,然後指定初始項目物件數目與並行項目的最大數目,選擇性地指定系統號誌物件的名稱,以及指定接收值的變數,指出是否已建立新的系統號誌。
public:
Semaphore(int initialCount, int maximumCount, System::String ^ name, [Runtime::InteropServices::Out] bool % createdNew);
public Semaphore (int initialCount, int maximumCount, string name, out bool createdNew);
public Semaphore (int initialCount, int maximumCount, string? name, out bool createdNew);
new System.Threading.Semaphore : int * int * string * bool -> System.Threading.Semaphore
Public Sub New (initialCount As Integer, maximumCount As Integer, name As String, ByRef createdNew As Boolean)
參數
- initialCount
- Int32
可以同時滿足之號誌要求的初始數目。
- maximumCount
- Int32
可以同時滿足之號誌要求的最大數目。
- name
- String
如果同步物件要與其他處理序共用,則為名稱;否則為 null
或空字串。 名稱區分大小寫。 (\) 保留反斜杠字元,而且只能用來指定命名空間。 如需命名空間的詳細資訊,請參閱一節。 視操作系統而定,名稱可能會有進一步的限制。 例如,在 Unix 作業系統上,排除命名空間之後的名稱必須是有效的檔名。
- createdNew
- Boolean
這個方法傳回時,如果已建立本機號誌 (也就是說,如果 name
為 null
或空字串),或是已建立指定的已命名系統號誌,則會包含 true
;如果指定的已命名系統號誌已存在則為 false
。 這個參數會以未初始化的狀態傳遞。
例外狀況
initialCount
大於 maximumCount
。
-或-
僅限 .NET Framework:name
的長度超過 MAX_PATH (260 個字元)。
name
無效。 這可能基於數種原因,其中包括可能由作業系統設定的一些限制,例如未知前置詞或無效字元。 請注意,名稱和通用前置詞 「Global\」 和 「Local\」 會區分大小寫。
-或-
發生一些其他錯誤。
HResult
屬性可提供詳細資訊。
僅限 Windows:name
已指定未知命名空間。 請參閱物件名稱 \(英文\) 以取得詳細資訊。
name
太長。 長度限制可能會取決於作業系統或設定。
具名信號已存在,並且具有存取控制安全性,而使用者沒有 FullControl。
無法建立具有所提供 name
的同步物件。 不同類型的同步物件可能具有相同名稱。
範例
下列程式代碼範例示範具名號誌的跨進程行為。 此範例會建立具名號誌,其計數上限為 5,初始計數為 2。 也就是說,它會為呼叫建構函式的線程保留三個專案。 如果 createNew
為 false
,則程式會對方法進行三次呼叫 WaitOne 。 因此,如果您從兩個命令視窗執行編譯的範例,第二個複本會在第三次呼叫 WaitOne時封鎖 。 釋放程式第一個複本中的一或多個專案,以解除封鎖第二個複本。
#using <System.dll>
using namespace System;
using namespace System::Threading;
public ref class Example
{
public:
static void main()
{
// The value of this variable is set by the semaphore
// constructor. It is true if the named system semaphore was
// created, and false if the named semaphore already existed.
//
bool semaphoreWasCreated;
// Create a Semaphore object that represents the named
// system semaphore "SemaphoreExample". The semaphore has a
// maximum count of five, and an initial count of two. The
// Boolean value that indicates creation of the underlying
// system object is placed in semaphoreWasCreated.
//
Semaphore^ sem = gcnew Semaphore( 2,5,L"SemaphoreExample",
semaphoreWasCreated );
if ( semaphoreWasCreated )
{
// If the named system semaphore was created, its count is
// set to the initial count requested in the constructor.
// In effect, the current thread has entered the semaphore
// three times.
//
Console::WriteLine( L"Entered the semaphore three times." );
}
else
{
// If the named system semaphore was not created,
// attempt to enter it three times. If another copy of
// this program is already running, only the first two
// requests can be satisfied. The third blocks.
//
sem->WaitOne();
Console::WriteLine( L"Entered the semaphore once." );
sem->WaitOne();
Console::WriteLine( L"Entered the semaphore twice." );
sem->WaitOne();
Console::WriteLine( L"Entered the semaphore three times." );
}
// The thread executing this program has entered the
// semaphore three times. If a second copy of the program
// is run, it will block until this program releases the
// semaphore at least once.
//
Console::WriteLine( L"Enter the number of times to call Release." );
int n;
if ( Int32::TryParse( Console::ReadLine(), n ) )
{
sem->Release( n );
}
int remaining = 3 - n;
if ( remaining > 0 )
{
Console::WriteLine( L"Press Enter to release the remaining "
L"count ({0}) and exit the program.", remaining );
Console::ReadLine();
sem->Release( remaining );
}
}
};
using System;
using System.Threading;
public class Example
{
public static void Main()
{
// The value of this variable is set by the semaphore
// constructor. It is true if the named system semaphore was
// created, and false if the named semaphore already existed.
//
bool semaphoreWasCreated;
// Create a Semaphore object that represents the named
// system semaphore "SemaphoreExample". The semaphore has a
// maximum count of five, and an initial count of two. The
// Boolean value that indicates creation of the underlying
// system object is placed in semaphoreWasCreated.
//
Semaphore sem = new Semaphore(2, 5, "SemaphoreExample",
out semaphoreWasCreated);
if (semaphoreWasCreated)
{
// If the named system semaphore was created, its count is
// set to the initial count requested in the constructor.
// In effect, the current thread has entered the semaphore
// three times.
//
Console.WriteLine("Entered the semaphore three times.");
}
else
{
// If the named system semaphore was not created,
// attempt to enter it three times. If another copy of
// this program is already running, only the first two
// requests can be satisfied. The third blocks.
//
sem.WaitOne();
Console.WriteLine("Entered the semaphore once.");
sem.WaitOne();
Console.WriteLine("Entered the semaphore twice.");
sem.WaitOne();
Console.WriteLine("Entered the semaphore three times.");
}
// The thread executing this program has entered the
// semaphore three times. If a second copy of the program
// is run, it will block until this program releases the
// semaphore at least once.
//
Console.WriteLine("Enter the number of times to call Release.");
int n;
if (int.TryParse(Console.ReadLine(), out n))
{
sem.Release(n);
}
int remaining = 3 - n;
if (remaining > 0)
{
Console.WriteLine("Press Enter to release the remaining " +
"count ({0}) and exit the program.", remaining);
Console.ReadLine();
sem.Release(remaining);
}
}
}
Imports System.Threading
Public Class Example
<MTAThread> _
Public Shared Sub Main()
' The value of this variable is set by the semaphore
' constructor. It is True if the named system semaphore was
' created, and False if the named semaphore already existed.
'
Dim semaphoreWasCreated As Boolean
' Create a Semaphore object that represents the named
' system semaphore "SemaphoreExample". The semaphore has a
' maximum count of five, and an initial count of two. The
' Boolean value that indicates creation of the underlying
' system object is placed in semaphoreWasCreated.
'
Dim sem As New Semaphore(2, 5, "SemaphoreExample", _
semaphoreWasCreated)
If semaphoreWasCreated Then
' If the named system semaphore was created, its count is
' set to the initial count requested in the constructor.
' In effect, the current thread has entered the semaphore
' three times.
'
Console.WriteLine("Entered the semaphore three times.")
Else
' If the named system semaphore was not created,
' attempt to enter it three times. If another copy of
' this program is already running, only the first two
' requests can be satisfied. The third blocks.
'
sem.WaitOne()
Console.WriteLine("Entered the semaphore once.")
sem.WaitOne()
Console.WriteLine("Entered the semaphore twice.")
sem.WaitOne()
Console.WriteLine("Entered the semaphore three times.")
End If
' The thread executing this program has entered the
' semaphore three times. If a second copy of the program
' is run, it will block until this program releases the
' semaphore at least once.
'
Console.WriteLine("Enter the number of times to call Release.")
Dim n As Integer
If Integer.TryParse(Console.ReadLine(), n) Then
sem.Release(n)
End If
Dim remaining As Integer = 3 - n
If (remaining) > 0 Then
Console.WriteLine("Press Enter to release the remaining " _
& "count ({0}) and exit the program.", remaining)
Console.ReadLine()
sem.Release(remaining)
End If
End Sub
End Class
備註
name
前面可能會加上 Global\
或 Local\
,以指定命名空間。
Global
指定命名空間時,同步處理物件可能會與系統上的任何進程共用。
Local
指定命名空間時,這也是未指定命名空間時的預設值,同步處理物件可能會與相同會話中的進程共用。 在 Windows 上,會話是登入工作階段,而服務通常會在不同的非互動式會話中執行。 在類似 Unix 的作業系統上,每個殼層都有自己的會話。 會話本機同步處理物件可能適用於在進程與父子關聯性之間同步處理,而它們全都在相同的會話中執行。 如需 Windows 上同步處理物件名稱的詳細資訊,請參閱 物件名稱。
如果 已提供 , name
且要求之型別的同步處理物件已存在於 命名空間中,則會使用現有的同步處理物件。 如果命名空間中已經有不同類型的同步處理物件, WaitHandleCannotBeOpenedException
則會擲回 。 否則,會建立新的同步處理物件。
這個建構函式會 Semaphore 初始化 對象,這個物件表示具名系統號誌。 您可以建立多個 Semaphore 物件,代表相同的具名系統號誌。
如果具名系統號誌不存在,則會使用 和maximumCount
所initialCount
指定的初始計數和最大計數來建立。 如果具名系統號誌已經存在, initialCount
而且 maximumCount
未使用,雖然無效的值仍然會造成例外狀況。 用來 createdNew
判斷是否已建立系統號誌。
如果 initialCount
小於 maximumCount
,且 createdNew
為 true
,則效果會與目前線程呼叫 WaitOne (減去 initialCount
) maximumCount
次相同。
如果您指定 null
或的 name
空字串,就會建立本機號誌,就像您已呼叫 Semaphore(Int32, Int32) 建構函式多載一樣。 在這裡情況下, createdNew
一律 true
為 。
因為具名號誌在整個操作系統中都是可見的,所以可用來協調跨進程界限的資源使用。
警告
根據預設,具名號誌不限於建立它的使用者。 其他使用者可能能夠開啟和使用號誌,包括藉由多次取得號誌來干擾號誌,而不會釋放旗號。 若要限制特定使用者的存取,您可以使用建構函式多載,或在 SemaphoreAcl 建立具名號誌時傳入 SemaphoreSecurity 。 避免在執行程式代碼的系統上使用具名號誌,而不受存取限制。
另請參閱
適用於
Semaphore(Int32, Int32, String, Boolean, SemaphoreSecurity)
初始化 Semaphore 類別的新執行個體,然後指定初始項目數目與並行項目的最大數目,選擇性地指定系統號誌物件的名稱,指定接收值的變數 (以指示是否已建立新的系統號誌),以及指定系統號誌的安全性存取控制。
public:
Semaphore(int initialCount, int maximumCount, System::String ^ name, [Runtime::InteropServices::Out] bool % createdNew, System::Security::AccessControl::SemaphoreSecurity ^ semaphoreSecurity);
public Semaphore (int initialCount, int maximumCount, string name, out bool createdNew, System.Security.AccessControl.SemaphoreSecurity semaphoreSecurity);
new System.Threading.Semaphore : int * int * string * bool * System.Security.AccessControl.SemaphoreSecurity -> System.Threading.Semaphore
Public Sub New (initialCount As Integer, maximumCount As Integer, name As String, ByRef createdNew As Boolean, semaphoreSecurity As SemaphoreSecurity)
參數
- initialCount
- Int32
可以同時滿足之號誌要求的初始數目。
- maximumCount
- Int32
可以同時滿足之號誌要求的最大數目。
- name
- String
如果同步物件要與其他處理序共用,則為名稱;否則為 null
或空字串。 名稱區分大小寫。 (\) 保留反斜杠字元,而且只能用來指定命名空間。 如需命名空間的詳細資訊,請參閱一節。 視操作系統而定,名稱可能會有進一步的限制。 例如,在 Unix 作業系統上,排除命名空間之後的名稱必須是有效的檔名。
- createdNew
- Boolean
這個方法傳回時,如果已建立本機號誌 (也就是說,如果 name
為 null
或空字串),或是已建立指定的已命名系統號誌,則會包含 true
;如果指定的已命名系統號誌已存在則為 false
。 這個參數會以未初始化的狀態傳遞。
- semaphoreSecurity
- SemaphoreSecurity
SemaphoreSecurity 物件,表示要套用到具名系統旗號的存取控制安全性。
例外狀況
initialCount
大於 maximumCount
。
-或-
僅限 .NET Framework:name
的長度超過 MAX_PATH (260 個字元)。
具名信號已存在,並且具有存取控制安全性,而使用者沒有 FullControl。
name
無效。 這可能基於數種原因,其中包括可能由作業系統設定的一些限制,例如未知前置詞或無效字元。 請注意,名稱和通用前置詞 「Global\」 和 「Local\」 會區分大小寫。
-或-
發生一些其他錯誤。
HResult
屬性可提供詳細資訊。
僅限 Windows:name
已指定未知命名空間。 請參閱物件名稱 \(英文\) 以取得詳細資訊。
name
太長。 長度限制可能會取決於作業系統或設定。
無法建立具有所提供 name
的同步物件。 不同類型的同步物件可能具有相同名稱。
範例
下列程式代碼範例示範具有訪問控制安全性之具名號誌的跨進程行為。 此範例會 OpenExisting(String) 使用 方法多載來測試具名號誌是否存在。 如果旗號不存在,則會建立其計數上限為 2,且訪問控制安全性會拒絕目前使用者使用旗號的許可權,但授與號誌的讀取和變更許可權的許可權。 如果您從兩個命令窗口執行編譯的範例,第二個複本會在呼叫 OpenExisting(String) 方法時擲回存取違規例外狀況。 攔截到例外狀況,而此範例會 OpenExisting(String, SemaphoreRights) 使用 方法多載來開啟號誌,並具有讀取和變更許可權所需的許可權。
變更許可權之後,旗號會以輸入和釋放所需的許可權開啟。 如果您從第三個命令視窗執行已編譯的範例,它會使用新的許可權來執行。
#using <System.dll>
using namespace System;
using namespace System::Threading;
using namespace System::Security::AccessControl;
using namespace System::Security::Permissions;
public ref class Example
{
public:
[SecurityPermissionAttribute(SecurityAction::Demand, Flags = SecurityPermissionFlag::UnmanagedCode)]
static void main()
{
String^ semaphoreName = L"SemaphoreExample5";
Semaphore^ sem = nullptr;
bool doesNotExist = false;
bool unauthorized = false;
// Attempt to open the named semaphore.
try
{
// Open the semaphore with (SemaphoreRights.Synchronize
// | SemaphoreRights.Modify), to enter and release the
// named semaphore.
//
sem = Semaphore::OpenExisting( semaphoreName );
}
catch ( WaitHandleCannotBeOpenedException^ ex )
{
Console::WriteLine( L"Semaphore does not exist." );
doesNotExist = true;
}
catch ( UnauthorizedAccessException^ ex )
{
Console::WriteLine( L"Unauthorized access: {0}", ex->Message );
unauthorized = true;
}
// There are three cases: (1) The semaphore does not exist.
// (2) The semaphore exists, but the current user doesn't
// have access. (3) The semaphore exists and the user has
// access.
//
if ( doesNotExist )
{
// The semaphore does not exist, so create it.
//
// The value of this variable is set by the semaphore
// constructor. It is true if the named system semaphore was
// created, and false if the named semaphore already existed.
//
bool semaphoreWasCreated;
// Create an access control list (ACL) that denies the
// current user the right to enter or release the
// semaphore, but allows the right to read and change
// security information for the semaphore.
//
String^ user = String::Concat( Environment::UserDomainName,
L"\\", Environment::UserName );
SemaphoreSecurity^ semSec = gcnew SemaphoreSecurity;
SemaphoreAccessRule^ rule = gcnew SemaphoreAccessRule( user,
static_cast<SemaphoreRights>(
SemaphoreRights::Synchronize |
SemaphoreRights::Modify ),
AccessControlType::Deny );
semSec->AddAccessRule( rule );
rule = gcnew SemaphoreAccessRule( user,
static_cast<SemaphoreRights>(
SemaphoreRights::ReadPermissions |
SemaphoreRights::ChangePermissions ),
AccessControlType::Allow );
semSec->AddAccessRule( rule );
// Create a Semaphore object that represents the system
// semaphore named by the constant 'semaphoreName', with
// maximum count three, initial count three, and the
// specified security access. The Boolean value that
// indicates creation of the underlying system object is
// placed in semaphoreWasCreated.
//
sem = gcnew Semaphore( 3,3,semaphoreName,semaphoreWasCreated,semSec );
// If the named system semaphore was created, it can be
// used by the current instance of this program, even
// though the current user is denied access. The current
// program enters the semaphore. Otherwise, exit the
// program.
//
if ( semaphoreWasCreated )
{
Console::WriteLine( L"Created the semaphore." );
}
else
{
Console::WriteLine( L"Unable to create the semaphore." );
return;
}
}
else if ( unauthorized )
{
// Open the semaphore to read and change the access
// control security. The access control security defined
// above allows the current user to do this.
//
try
{
sem = Semaphore::OpenExisting( semaphoreName,
static_cast<SemaphoreRights>(
SemaphoreRights::ReadPermissions |
SemaphoreRights::ChangePermissions ));
// Get the current ACL. This requires
// SemaphoreRights.ReadPermissions.
SemaphoreSecurity^ semSec = sem->GetAccessControl();
String^ user = String::Concat( Environment::UserDomainName,
L"\\", Environment::UserName );
// First, the rule that denied the current user
// the right to enter and release the semaphore must
// be removed.
SemaphoreAccessRule^ rule = gcnew SemaphoreAccessRule( user,
static_cast<SemaphoreRights>(
SemaphoreRights::Synchronize |
SemaphoreRights::Modify ),
AccessControlType::Deny );
semSec->RemoveAccessRule( rule );
// Now grant the user the correct rights.
//
rule = gcnew SemaphoreAccessRule( user,
static_cast<SemaphoreRights>(
SemaphoreRights::Synchronize |
SemaphoreRights::Modify ),
AccessControlType::Allow );
semSec->AddAccessRule( rule );
// Update the ACL. This requires
// SemaphoreRights.ChangePermissions.
sem->SetAccessControl( semSec );
Console::WriteLine( L"Updated semaphore security." );
// Open the semaphore with (SemaphoreRights.Synchronize
// | SemaphoreRights.Modify), the rights required to
// enter and release the semaphore.
//
sem = Semaphore::OpenExisting( semaphoreName );
}
catch ( UnauthorizedAccessException^ ex )
{
Console::WriteLine( L"Unable to change permissions: {0}", ex->Message );
return;
}
}
// Enter the semaphore, and hold it until the program
// exits.
//
try
{
sem->WaitOne();
Console::WriteLine( L"Entered the semaphore." );
Console::WriteLine( L"Press the Enter key to exit." );
Console::ReadLine();
sem->Release();
}
catch ( UnauthorizedAccessException^ ex )
{
Console::WriteLine( L"Unauthorized access: {0}", ex->Message );
}
}
};
using System;
using System.Threading;
using System.Security.AccessControl;
internal class Example
{
internal static void Main()
{
const string semaphoreName = "SemaphoreExample5";
Semaphore sem = null;
bool doesNotExist = false;
bool unauthorized = false;
// Attempt to open the named semaphore.
try
{
// Open the semaphore with (SemaphoreRights.Synchronize
// | SemaphoreRights.Modify), to enter and release the
// named semaphore.
//
sem = Semaphore.OpenExisting(semaphoreName);
}
catch(WaitHandleCannotBeOpenedException)
{
Console.WriteLine("Semaphore does not exist.");
doesNotExist = true;
}
catch(UnauthorizedAccessException ex)
{
Console.WriteLine("Unauthorized access: {0}", ex.Message);
unauthorized = true;
}
// There are three cases: (1) The semaphore does not exist.
// (2) The semaphore exists, but the current user doesn't
// have access. (3) The semaphore exists and the user has
// access.
//
if (doesNotExist)
{
// The semaphore does not exist, so create it.
//
// The value of this variable is set by the semaphore
// constructor. It is true if the named system semaphore was
// created, and false if the named semaphore already existed.
//
bool semaphoreWasCreated;
// Create an access control list (ACL) that denies the
// current user the right to enter or release the
// semaphore, but allows the right to read and change
// security information for the semaphore.
//
string user = Environment.UserDomainName + "\\"
+ Environment.UserName;
SemaphoreSecurity semSec = new SemaphoreSecurity();
SemaphoreAccessRule rule = new SemaphoreAccessRule(
user,
SemaphoreRights.Synchronize | SemaphoreRights.Modify,
AccessControlType.Deny);
semSec.AddAccessRule(rule);
rule = new SemaphoreAccessRule(
user,
SemaphoreRights.ReadPermissions | SemaphoreRights.ChangePermissions,
AccessControlType.Allow);
semSec.AddAccessRule(rule);
// Create a Semaphore object that represents the system
// semaphore named by the constant 'semaphoreName', with
// maximum count three, initial count three, and the
// specified security access. The Boolean value that
// indicates creation of the underlying system object is
// placed in semaphoreWasCreated.
//
sem = new Semaphore(3, 3, semaphoreName,
out semaphoreWasCreated, semSec);
// If the named system semaphore was created, it can be
// used by the current instance of this program, even
// though the current user is denied access. The current
// program enters the semaphore. Otherwise, exit the
// program.
//
if (semaphoreWasCreated)
{
Console.WriteLine("Created the semaphore.");
}
else
{
Console.WriteLine("Unable to create the semaphore.");
return;
}
}
else if (unauthorized)
{
// Open the semaphore to read and change the access
// control security. The access control security defined
// above allows the current user to do this.
//
try
{
sem = Semaphore.OpenExisting(
semaphoreName,
SemaphoreRights.ReadPermissions
| SemaphoreRights.ChangePermissions);
// Get the current ACL. This requires
// SemaphoreRights.ReadPermissions.
SemaphoreSecurity semSec = sem.GetAccessControl();
string user = Environment.UserDomainName + "\\"
+ Environment.UserName;
// First, the rule that denied the current user
// the right to enter and release the semaphore must
// be removed.
SemaphoreAccessRule rule = new SemaphoreAccessRule(
user,
SemaphoreRights.Synchronize | SemaphoreRights.Modify,
AccessControlType.Deny);
semSec.RemoveAccessRule(rule);
// Now grant the user the correct rights.
//
rule = new SemaphoreAccessRule(user,
SemaphoreRights.Synchronize | SemaphoreRights.Modify,
AccessControlType.Allow);
semSec.AddAccessRule(rule);
// Update the ACL. This requires
// SemaphoreRights.ChangePermissions.
sem.SetAccessControl(semSec);
Console.WriteLine("Updated semaphore security.");
// Open the semaphore with (SemaphoreRights.Synchronize
// | SemaphoreRights.Modify), the rights required to
// enter and release the semaphore.
//
sem = Semaphore.OpenExisting(semaphoreName);
}
catch(UnauthorizedAccessException ex)
{
Console.WriteLine("Unable to change permissions: {0}", ex.Message);
return;
}
}
// Enter the semaphore, and hold it until the program
// exits.
//
try
{
sem.WaitOne();
Console.WriteLine("Entered the semaphore.");
Console.WriteLine("Press the Enter key to exit.");
Console.ReadLine();
sem.Release();
}
catch(UnauthorizedAccessException ex)
{
Console.WriteLine("Unauthorized access: {0}", ex.Message);
}
}
}
Imports System.Threading
Imports System.Security.AccessControl
Friend Class Example
<MTAThread> _
Friend Shared Sub Main()
Const semaphoreName As String = "SemaphoreExample5"
Dim sem As Semaphore = Nothing
Dim doesNotExist as Boolean = False
Dim unauthorized As Boolean = False
' Attempt to open the named semaphore.
Try
' Open the semaphore with (SemaphoreRights.Synchronize
' Or SemaphoreRights.Modify), to enter and release the
' named semaphore.
'
sem = Semaphore.OpenExisting(semaphoreName)
Catch ex As WaitHandleCannotBeOpenedException
Console.WriteLine("Semaphore does not exist.")
doesNotExist = True
Catch ex As UnauthorizedAccessException
Console.WriteLine("Unauthorized access: {0}", ex.Message)
unauthorized = True
End Try
' There are three cases: (1) The semaphore does not exist.
' (2) The semaphore exists, but the current user doesn't
' have access. (3) The semaphore exists and the user has
' access.
'
If doesNotExist Then
' The semaphore does not exist, so create it.
'
' The value of this variable is set by the semaphore
' constructor. It is True if the named system semaphore was
' created, and False if the named semaphore already existed.
'
Dim semaphoreWasCreated As Boolean
' Create an access control list (ACL) that denies the
' current user the right to enter or release the
' semaphore, but allows the right to read and change
' security information for the semaphore.
'
Dim user As String = Environment.UserDomainName _
& "\" & Environment.UserName
Dim semSec As New SemaphoreSecurity()
Dim rule As New SemaphoreAccessRule(user, _
SemaphoreRights.Synchronize Or SemaphoreRights.Modify, _
AccessControlType.Deny)
semSec.AddAccessRule(rule)
rule = New SemaphoreAccessRule(user, _
SemaphoreRights.ReadPermissions Or _
SemaphoreRights.ChangePermissions, _
AccessControlType.Allow)
semSec.AddAccessRule(rule)
' Create a Semaphore object that represents the system
' semaphore named by the constant 'semaphoreName', with
' maximum count three, initial count three, and the
' specified security access. The Boolean value that
' indicates creation of the underlying system object is
' placed in semaphoreWasCreated.
'
sem = New Semaphore(3, 3, semaphoreName, _
semaphoreWasCreated, semSec)
' If the named system semaphore was created, it can be
' used by the current instance of this program, even
' though the current user is denied access. The current
' program enters the semaphore. Otherwise, exit the
' program.
'
If semaphoreWasCreated Then
Console.WriteLine("Created the semaphore.")
Else
Console.WriteLine("Unable to create the semaphore.")
Return
End If
ElseIf unauthorized Then
' Open the semaphore to read and change the access
' control security. The access control security defined
' above allows the current user to do this.
'
Try
sem = Semaphore.OpenExisting(semaphoreName, _
SemaphoreRights.ReadPermissions Or _
SemaphoreRights.ChangePermissions)
' Get the current ACL. This requires
' SemaphoreRights.ReadPermissions.
Dim semSec As SemaphoreSecurity = sem.GetAccessControl()
Dim user As String = Environment.UserDomainName _
& "\" & Environment.UserName
' First, the rule that denied the current user
' the right to enter and release the semaphore must
' be removed.
Dim rule As New SemaphoreAccessRule(user, _
SemaphoreRights.Synchronize Or SemaphoreRights.Modify, _
AccessControlType.Deny)
semSec.RemoveAccessRule(rule)
' Now grant the user the correct rights.
'
rule = New SemaphoreAccessRule(user, _
SemaphoreRights.Synchronize Or SemaphoreRights.Modify, _
AccessControlType.Allow)
semSec.AddAccessRule(rule)
' Update the ACL. This requires
' SemaphoreRights.ChangePermissions.
sem.SetAccessControl(semSec)
Console.WriteLine("Updated semaphore security.")
' Open the semaphore with (SemaphoreRights.Synchronize
' Or SemaphoreRights.Modify), the rights required to
' enter and release the semaphore.
'
sem = Semaphore.OpenExisting(semaphoreName)
Catch ex As UnauthorizedAccessException
Console.WriteLine("Unable to change permissions: {0}", _
ex.Message)
Return
End Try
End If
' Enter the semaphore, and hold it until the program
' exits.
'
Try
sem.WaitOne()
Console.WriteLine("Entered the semaphore.")
Console.WriteLine("Press the Enter key to exit.")
Console.ReadLine()
sem.Release()
Catch ex As UnauthorizedAccessException
Console.WriteLine("Unauthorized access: {0}", _
ex.Message)
End Try
End Sub
End Class
備註
使用此建構函式,在建立時將訪問控制安全性套用至具名系統號誌,以防止其他程式代碼控制旗號。
name
前面可能會加上 Global\
或 Local\
,以指定命名空間。
Global
指定命名空間時,同步處理物件可能會與系統上的任何進程共用。
Local
指定命名空間時,這也是未指定命名空間時的預設值,同步處理物件可能會與相同會話中的進程共用。 在 Windows 上,會話是登入工作階段,而服務通常會在不同的非互動式會話中執行。 在類似 Unix 的作業系統上,每個殼層都有自己的會話。 會話本機同步處理物件可能適用於在進程與父/子關聯性之間同步處理,其中它們全都在相同會話中執行。 如需 Windows 上同步處理物件名稱的詳細資訊,請參閱 物件名稱。
name
如果 已提供 ,且要求的型別同步處理物件已存在於命名空間中,則會使用現有的同步處理物件。 如果命名空間中已經存在不同類型的同步處理物件, WaitHandleCannotBeOpenedException
則會擲回 。 否則,會建立新的同步處理物件。
這個建構函式會 Semaphore 初始化 物件,此物件表示具名系統旗號。 您可以建立多個 Semaphore 物件,代表相同的具名系統旗號。
如果具名系統旗號不存在,則會使用指定的訪問控制安全性來建立它。 如果具名旗號存在,則會忽略指定的訪問控制安全性。
注意
即使semaphoreSecurity
拒絕或無法將某些訪問許可權授與目前使用者,呼叫端仍可完全控制新建立Semaphore的物件。 不過,如果目前用戶嘗試取得另一個 Semaphore 物件來代表相同的具名旗號,請使用建構函式或 OpenExisting 方法,套用 Windows 存取控制安全性。
如果具名系統旗號不存在,則會使用 和 所initialCount
maximumCount
指定的初始計數和最大計數來建立。 如果具名系統旗號已經存在,而且maximumCount
未使用,initialCount
但無效的值仍會造成例外狀況。
createdNew
使用 參數來判斷系統旗號是否由這個建構函式建立。
如果 initialCount
小於 maximumCount
,且 createdNew
為 true
,則效果會與目前線程呼叫 WaitOne (maximumCount
減) initialCount
次相同。
如果您為 指定 null
或空字串 name
,就會建立本機旗號,就像您呼叫 Semaphore(Int32, Int32) 建構函式多載一樣。 在這裡情況下, createdNew
一律 true
為 。
由於在操作系統中可以看到具名旗號,因此可用來協調跨進程界限的資源使用。
警告
根據預設,具名旗號不限於建立它的使用者。 其他使用者可能能夠開啟和使用旗號,包括藉由取得信號多次而干擾旗號,而不會釋放旗號。 若要限制特定使用者的存取權,您可以在建立具名旗號時傳入 SemaphoreSecurity 。 避免在執行程式代碼的系統上使用具名旗號,而不需存取限制。