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)
- Source:
- Semaphore.cs
- Source:
- Semaphore.cs
- Source:
- 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,初始计数为 0。 该示例启动五个线程,这些线程阻止等待信号灯。 主线程使用 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 (maximumCount
减 initialCount
) 次相同。 如果不想为创建信号灯的线程保留任何条目,请为 maximumCount
和 initialCount
使用相同的数字。
另请参阅
适用于
Semaphore(Int32, Int32, String)
- Source:
- Semaphore.cs
- Source:
- Semaphore.cs
- Source:
- 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 的操作系统上,排除命名空间后的名称必须是有效的文件名。
例外
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
可以使用 或 Local\
作为前缀Global\
来指定命名空间。
Global
指定命名空间后,可以与系统上的任何进程共享同步对象。 如果指定了 Local
命名空间(如果未指定命名空间,这也是默认命名空间),则同步对象可以与同一会话中的进程共享。 在 Windows 上,会话是登录会话,服务通常在不同的非交互式会话中运行。 在类似 Unix 的操作系统上,每个 shell 都有自己的会话。 会话本地同步对象可能适合在具有父/子关系的进程之间进行同步,这些进程都在同一会话中运行。 有关 Windows 上的同步对象名称的详细信息,请参阅 对象名称。
如果提供了 , name
并且命名空间中已存在请求类型的同步对象,则使用现有同步对象。 如果命名空间中已存在不同类型的同步对象, WaitHandleCannotBeOpenedException
则会引发 。 否则,将创建新的同步对象。
如果命名的系统信号量不存在,则会使用 和 maximumCount
指定initialCount
的初始计数和最大计数来创建它。 如果已命名的系统信号灯已存在, initialCount
则 maximumCount
未使用 ,但无效值仍会导致异常。 如果需要确定是否创建了命名系统信号量,请改用 Semaphore(Int32, Int32, String, Boolean) 构造函数重载。
重要
使用此构造函数重载时,建议的做法是为 和 maximumCount
指定相同的数字initialCount
。 如果 initialCount
小于 maximumCount
,并且创建了命名系统信号灯,则效果与当前线程调用 WaitOne (maximumCount
减 initialCount
去) 次相同。 但是,对于此构造函数重载,无法确定是否创建了命名的系统信号量。
如果为 name
指定或为 指定null
空字符串,则会创建本地信号灯,就像调用构造函数重载一Semaphore(Int32, Int32)样。
由于命名信号量在整个操作系统中可见,因此它们可用于跨进程边界协调资源使用。
如果要了解命名系统信号量是否存在,请使用 OpenExisting 方法。 方法 OpenExisting 尝试打开现有的命名信号灯,如果系统信号灯不存在,则会引发异常。
注意
默认情况下,命名信号灯不限于创建它的用户。 其他用户可能能够打开和使用信号灯,包括通过多次获取信号灯而不释放信号灯来干扰信号灯。 若要限制对特定用户的访问,可以使用构造函数重载,或者在 SemaphoreAcl 创建命名信号量时传入 SemaphoreSecurity 。 避免在可能有不受信任的用户运行代码的系统上使用没有访问限制的命名信号量。
另请参阅
适用于
Semaphore(Int32, Int32, String, Boolean)
- Source:
- Semaphore.cs
- Source:
- Semaphore.cs
- Source:
- 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
。 此参数未经初始化即被传递。
例外
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
可以使用 或 Local\
作为前缀Global\
来指定命名空间。
Global
指定命名空间后,可以与系统上的任何进程共享同步对象。 如果指定了 Local
命名空间(如果未指定命名空间,这也是默认命名空间),则同步对象可以与同一会话中的进程共享。 在 Windows 上,会话是登录会话,服务通常在不同的非交互式会话中运行。 在类似 Unix 的操作系统上,每个 shell 都有自己的会话。 会话本地同步对象可能适合在具有父/子关系的进程之间进行同步,这些进程都在同一会话中运行。 有关 Windows 上的同步对象名称的详细信息,请参阅 对象名称。
如果提供了 , name
并且命名空间中已存在请求类型的同步对象,则使用现有同步对象。 如果命名空间中已存在不同类型的同步对象, WaitHandleCannotBeOpenedException
则会引发 。 否则,将创建新的同步对象。
此构造函数初始化表示 Semaphore 命名系统信号灯的 对象。 可以创建表示同一命名系统信号灯的多个 Semaphore 对象。
如果命名的系统信号量不存在,则会使用 和 maximumCount
指定initialCount
的初始计数和最大计数来创建它。 如果已命名的系统信号灯已存在, initialCount
则 maximumCount
未使用 ,但无效值仍会导致异常。 使用 createdNew
确定是否创建了系统信号灯。
如果 initialCount
小于 maximumCount
且 createdNew
为 true
,则效果与当前线程调用 WaitOne (maximumCount
减 initialCount
去) 次相同。
如果为 name
指定或为 指定null
空字符串,则会创建本地信号灯,就像调用构造函数重载一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 对象,表示应用于已命名的系统信号量的访问控制安全性。
例外
命名信号量存在且具有访问控制安全性,用户不具有 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
可以使用 或 Local\
作为前缀Global\
来指定命名空间。
Global
指定命名空间后,可以与系统上的任何进程共享同步对象。 如果指定了 Local
命名空间(如果未指定命名空间,这也是默认命名空间),则同步对象可以与同一会话中的进程共享。 在 Windows 上,会话是登录会话,服务通常在不同的非交互式会话中运行。 在类似 Unix 的操作系统上,每个 shell 都有自己的会话。 会话本地同步对象可能适合用于使用父/子关系(在这些进程都在同一会话中运行)之间进行同步。 有关 Windows 上的同步对象名称的详细信息,请参阅 对象名称。
如果提供了 , name
并且命名空间中已存在所请求类型的同步对象,则使用现有同步对象。 如果命名空间中已存在不同类型的同步对象, WaitHandleCannotBeOpenedException
则会引发 。 否则,将创建新的同步对象。
此构造函数初始化一个 Semaphore 对象,该对象表示命名的系统信号量。 可以创建表示同一命名系统信号量的多个 Semaphore 对象。
如果命名的系统信号量不存在,则会使用指定的访问控制安全性创建它。 如果命名信号量存在,则忽略指定的访问控制安全性。
注意
调用方可以完全控制新创建 Semaphore 的对象,即使 semaphoreSecurity
拒绝或未能向当前用户授予某些访问权限。 但是,如果当前用户尝试使用构造函数或 OpenExisting 方法获取另一个Semaphore对象来表示同一个命名信号灯,则会应用 Windows 访问控制安全性。
如果命名的系统信号量不存在,则会使用 和 maximumCount
指定的initialCount
初始计数和最大计数来创建它。 如果命名的系统信号量已存在且 initialCount
maximumCount
未使用,但无效值仍会导致异常。
createdNew
使用 参数确定系统信号量是否由此构造函数创建。
如果 initialCount
小于 maximumCount
,且 createdNew
为 true
,则效果与当前线程调用 WaitOne (maximumCount
减去 initialCount
) 次相同。
如果为 name
指定null
或空字符串,则会创建本地信号量,就像调用Semaphore(Int32, Int32)构造函数重载一样。 在这种情况下, createdNew
始终 true
为 。
由于命名信号灯在整个操作系统中可见,因此它们可用于跨进程边界协调资源使用。
注意
默认情况下,命名信号量不仅限于创建它的用户。 其他用户可能能够打开和使用信号灯,包括通过多次获取信号灯而不释放信号灯来干扰信号量。 若要限制对特定用户的访问,可以在创建命名信号灯时传入 SemaphoreSecurity 。 避免在没有访问限制的情况下使用命名信号灯,这些信号灯对可能具有不受信任的用户运行代码的系统。