C# - 多线程 之 信号系统

基础概览

多线程之信号系统命名空间

using System.Threading;

线程同步类的继承层次关系图

 

终止状态和非终止状态

在终止状态下,被WaitOne()阻塞的线程会逐个得到释放。如果一个线程在EventWaitHandle对象处于终止状态时调用其WaitOne()方法,无法起到阻塞线程的作用,因为线程被其WaitOne()方法阻塞后,会立即被释放掉(实际不会阻塞)。

在非终止状态下,被WaitOne()阻塞的线程会继续被阻塞。如果一个线程在EventWaitHandle对象处于非终止状态时调用其WaitOne()方法,该线程会立即被阻塞。 

  • 非终止状态:WaitOne()阻塞线程
  • 终止状态:WaitOne()不阻塞线程,允许执行后续代码

:非终止/终止状态是针对事件来说...

WaitHandle

抽象基类,等待句柄,线程安全。

// 封装等待对共享资源的独占访问的操作系统特定的对象
public abstract class WaitHandle {
	public const int WaitTimeout = 258;
	protected WaitHandle();
	public void Dispose();
	public virtual void Close();
	// 阻止当前线程,直到当前System.Threading.WaitHandle(的实例)收到信号
	public virtual bool WaitOne();
	public virtual bool WaitAll(WaitHandle[] waitHandles, xxx);
	public virtual bool WaitAny(WaitHandle[] waitHandles, xxx);	
} 

EventWaitHandle

事件等待句柄,EventWaitHandle类表示一个线程同步事件,允许线程通过操作系统互发信号和等待彼此的信号达到线程同步的目的。调用其WaitOne()方法阻塞线程运行,直到得到一个通知信号(该信号由EventWaitHandle类的Set()方法发出),然后释放线程让其不再阻塞继续运行。

// 表示一个线程同步事件
public class EventWaitHandle : WaitHandle {
	public EventWaitHandle(bool initialState, EventResetMode mode, xxx);
	public bool Reset();  // 将事件状态设置为非终止状态,导致线程阻塞
	public bool Set();    // 将事件状态设置为终止状态,允许一个或多个等待线程继续执行
	public static EventWaitHandle OpenExisting(string name, xxx);  // 打开一个现有的已命名同步事件
} 

模式分类

public enum EventResetMode{
        AutoReset = 0,  ManualReset = 1,
}

区别:EventWaitHandle对象调用WaitOne()方法、在接收到通知信号后,是否自动调用Reset()方法重置。

AutoRest:自动重置模式。(EventWaitHandle类的子类:System.Threading.AutoResetEvent类)

当终止时,EventWaitHandle对象释放一个线程后并自动重置。如果没有等待的线程,EventWaitHandle对象将保持终止状态直到有一个线程阻止,并在释放此线程后重置。

ManualRest:手动重置模式。(EventWaitHandle类的子类:System.Threading.ManualRestEvent类)

当终止时,EventWaitHandle对象释放所有等待的线程,并保持终止状态直到手动重置。

注:终止状态和非终止状态之间可以相互转换,通常初始为非终止状态。  

方法

  • ReSet()方法:将事件状态设为非终止状态,导致线程阻塞;(设置需要等待的线程阻塞,即包含WaitOne()方法的线程阻塞)
  • Set()方法:将事件状态设为终止状态,允许一个或多个等待线程继续;(发送一个信号给操作系统,让处于等待的线程从阻塞态转换为运行态,即包含WaitOne()方法的线程不再阻塞)
  • WaitOne()方法:阻塞当前线程,直到当前的等待句柄收到信号(使本线程处于阻塞态直到收到信号为止,即当其他非阻塞线程调用set()方法时再继续执行)

示例

public static void EventWaitHandleDemo()
{
    // 测试ManualReset模式
    EventWaitHandle ReadyEvent = new EventWaitHandle(false, EventResetMode.ManualReset, "READY");
    // 测试AutoReset模式
    //EventWaitHandle ReadyEvent = new EventWaitHandle(false, EventResetMode.AutoReset, "READY");

    // 新线程
    Thread readyThread = new Thread((it) =>
    {
        Thread.Sleep(3000);
        ReadyEvent.Set();
    });
    readyThread.Start();
            
    if (!ReadyEvent.WaitOne(5000)){                
        Console.WriteLine("ready failed!");
    }else{
        Console.WriteLine("ready success!");
    }

    //ReadyEvent.Reset();   // AutoReset模式会在调用WaitOne后自动调用Reset()方法

    if (!ReadyEvent.WaitOne(5000)){
        Console.WriteLine("ready failed again!");
    }else{
        Console.WriteLine("ready success again!");
    }
}  

参考多线程编程中的EventWaitHandle示例

ManualResetEvent

// 通知一个或多个正在等待的线程已发生事件
public sealed class ManualResetEvent : EventWaitHandle {
    // 用一个指示是否将初始状态设置为终止的布尔值初始化ManualResetEvent类的实例
    public ManualResetEvent(bool initialState);
} 

 

AutoResetEvent

// 通知正在等待的线程已发生事件
public sealed class AutoResetEvent : EventWaitHandle {
    // 用一个指示是否将初始状态设置为终止的布尔值初始化AutoResetEvent类新实例
    public AutoResetEvent(bool initialState);
}

  

 

参考

  •  ;

 

posted @ 2016-11-06 22:57  万箭穿心,习惯就好。  阅读(2963)  评论(0编辑  收藏  举报