C#之:线程同步 WaitHandle类
WaitHandle:命名空间:System.Threading封装等待对共享资源进行独占访问的操作系统特定的对象。 WaitHandle:是一个抽象类,我们一般不直接用,而是用它的派生类:AutoResetEventEventWaitHandleManualResetEventMutexSemaphore详细信息请点击微软链接:WaitHandle一 AutoResetEv...
WaitHandle:
命名空间:System.Threading
封装等待对共享资源进行独占访问的操作系统特定的对象。 WaitHandle:是一个抽象类,我们一般不直接用,而是用它的派生类:
- AutoResetEvent
- EventWaitHandle
- ManualResetEvent
- Mutex
- Semaphore
详细信息请点击微软链接:WaitHandle
一 AutoResetEvent:
表示线程同步事件在一个等待线程释放后收到信号时自动重置。 此类不能被继承。
构造函数:
构造函数 | 描述 |
---|---|
AutoResetEvent(Boolean) | 用一个指示是否将初始状态设置为终止的布尔值初始化 AutoResetEvent 类的新实例。 |
常用方法 :
方法 | 描述 |
---|---|
Close() | 释放由当前 WaitHandle 占用的所有资源。 |
Dispose() | 释放由当前 WaitHandle 占用的所有资源。 |
WaitOne() | 阻止当前线程,直到当前 WaitHandle 收到信号。 |
WaitOne(Int32) | 阻止当前线程,直到当前 WaitHandle 收到信号,同时使用 32 位带符号整数指定时间间隔(以毫秒为单位)。 |
WaitOne(Int32, Boolean) | 阻止当前线程,直到当前的 WaitHandle 收到信号为止,同时使用 32 位带符号整数指定时间间隔,并指定是否在等前退出同步域。 |
属性:
属性 | 描述 |
---|---|
Handle | 获取或设置本机操作系统句柄。 |
SafeWaitHandle | 获取或设置本机操作系统句柄。 |
字段:
字段 | 描述 |
---|---|
WaitTimeout | 指示在任何等待句柄终止之前 WaitAny(WaitHandle[], Int32, Boolean) 操作已超时。 此字段为常数。 |
官方链接:AutoResetEvent
常用派生类
1. AutoResetEvent:
表示线程同步事件在一个等待线程释放后收到信号时自动重置。 此类不能被继承。
是一个自动阻塞,WaitOne() 方法阻塞程序执行,Set() 方法释放信息。当释放后阻塞的代码继续执行。但下一次执行还需要等待信号。
通俗的讲,WaitOne()是关门,Set()是开门。但开门之后。执行完又自动关上了,还需要开门。还可以指定超时时间:
are.WaitOne(1000);//指定超时一秒,如果一秒后没有信号程序继续执行
示例Dome:
static void Main(string[] args)
{
AutoResetEvent are = new AutoResetEvent(false); //初始状态为关,构造函数传入 false
Thread t1 = new Thread(() => {
Console.WriteLine("开始等着开门");
are.WaitOne();
Console.WriteLine("终于等到你");
});
t1.IsBackground = true;
t1.Start();
Console.WriteLine("按任意键开门");
Console.ReadKey();
are.Set();//开门
Console.ReadKey();
}
重要:
此类实现了 IDisposable 接口。 在使用完类型后,您应直接或间接释放类型。 若要直接释放类型,请在 try/catch 块中调用其 Dispose 方法。 若要间接释放类型,请使用 using(在 C# 中)
不保证每次调用Set方法都将释放一个线程。 如果两次调用都过于接近, 因此在释放线程之前发生第二次调用, 则只释放一个线程。 这就像第二次调用没有发生。 此外, 如果Set在没有等待的线程并且已发出信号的AutoResetEvent情况下调用, 则调用不起作用。
详细信息官方链接:AutoResetEvent
2. ManualResetEvent:
表示线程同步事件,收到信号时,必须手动重置该事件。 此类不能被继承。
与AutoResetEvent类刚好相反,ManualResetEvent是一旦设定Set()后就一直开门,除非调用Reset()关门。Manual:手动;Reset:关门。
示例Dome:
static void Main(string[] args)
{
//WaitOne()还可以设置等待超时时间:
ManualResetEvent m = new ManualResetEvent(false);
Thread t1 = new Thread(()=> {
Console.WriteLine("等着开门");
if(m.WaitOne(5000))
{
Console.WriteLine("终于等到你了");
}
else
{
Console.WriteLine("登录5秒还没等到你");
}
});
t1.Start();
Console.WriteLine("按任意键开门");
Console.ReadKey();
m.Set();//开门
Console.WriteLine("终于开门了");
Console.ReadKey();
}
详细信息官方链接:ManualResetEvent
WaitHandle.WaitAll(WaitHandle[] waitHandles)用来等待所有信号都变为“开门状态”,WaitHandle. WaitAny(WaitHandle[] waitHandles) 用来等待任意一个信号都变为“开门状态”。
3.EventWaitHandle
表示一个线程同步事件。
EventWaitHandle 的功能结合了前面两种。在构造函数中传入不同的参数,就会又不同的功能。
class Program
{
//EventWaitHandle用于演示自动重置和手动重置同步事件之间的区别。
private static EventWaitHandle ewh;
//一个计数器,确保在释放任何线程之前启动和阻塞所有线程。Long用于显示64位互锁方法的使用。
private static long threadCount = 0;
//一个自动重置事件,该事件允许主线程阻塞,直到退出的线程减少计数为止。
private static EventWaitHandle clearCount = new EventWaitHandle(false, EventResetMode.AutoReset);
[MTAThread]
public static void Main()
{
//创建一个自动重置EventWaitHandle。
ewh = new EventWaitHandle(false, EventResetMode.AutoReset);
// 创建并启动五个编号的线程。使用ParameterizedThreadStart委托,这样线程号就可以作为参数传递给Start方法。
for (int i = 0; i <= 4; i++)
{
Thread t = new Thread(
new ParameterizedThreadStart(ThreadProc)
);
t.Start(i);
}
//等待,直到所有线程都已启动和阻塞。当多个线程在32位系统上使用64位值时,必须通过联锁类访问该值,以确保线程安全。
while (Interlocked.Read(ref threadCount) < 5)
{
Thread.Sleep(500);
}
//每次用户按回车键释放一个线程,直到所有线程都被释放。
while (Interlocked.Read(ref threadCount) > 0)
{
Console.WriteLine("按ENTER键释放一个等待线程。");
Console.ReadLine();
//SignalAndWait向EventWaitHandle发出信号,EventWaitHandle在重置之前只释放一个线程,因为它是用AutoReset模式创建的。然后阻塞clearCount,以允许发出信号的线程在再次循环之前递减计数。
WaitHandle.SignalAndWait(ewh, clearCount);
}
Console.WriteLine();
//创建一个ManualReset EventWaitHandle。
ewh = new EventWaitHandle(false, EventResetMode.ManualReset);
//创建并启动另外五个编号的线程。
for (int i = 0; i <= 4; i++)
{
Thread t = new Thread(
new ParameterizedThreadStart(ThreadProc)
);
t.Start(i);
}
//等待,直到所有线程都已启动和阻塞。
while (Interlocked.Read(ref threadCount) < 5)
{
Thread.Sleep(500);
}
//因为EventWaitHandle是用ManualReset模式创建的,它发出释放所有等待线程的信号。
Console.WriteLine("按ENTER键释放等待的线程。");
Console.ReadLine();
ewh.Set();
Console.ReadKey();
}
public static void ThreadProc(object data)
{
int index = (int)data;
Console.WriteLine("Thread {0} blocks.", data);
//增加阻塞线程的数量。
Interlocked.Increment(ref threadCount);
// 等着EventWaitHandle.
ewh.WaitOne();
Console.WriteLine("Thread {0} exits.", data);
//减少阻塞线程的数量。
Interlocked.Decrement(ref threadCount);
//发出ewh信号后,主线程阻塞clearCount,直到发出信号的线程减少了计数。现在信号。
clearCount.Set();
}
}
详细信息官方链接:EventWaitHandle
更多推荐
所有评论(0)