C#多线程系列之手动线程通知

区别与示例

AutoResetEvent 和 ManualResetEvent 十分相似。两者之间的区别,在于前者是自动(Auto),后者是手动(Manua)。

你可以先运行下面的示例,再测试两者的区别。

AutoResetEvent 示例:

    class Program
    {
        // 线程通知
        private static AutoResetEvent resetEvent = new AutoResetEvent(false);

        static void Main(string[] args)
        {
            // 创建线程
            new Thread(DoOne).Start();

            // 用于不断向另一个线程发送信号
            while (true)
            {
                Console.ReadKey();
                resetEvent.Set();           // 发生通知,设置终止状态
            }
        }

        public static void DoOne()
        {
            Console.WriteLine("① 等待中,请发出信号允许我运行");
            resetEvent.WaitOne();

            Console.WriteLine("② 等待中,请发出信号允许我运行");

            resetEvent.WaitOne();
            Console.WriteLine("③ 等待中,请发出信号允许我运行");

            // ...

            Console.WriteLine("线程结束");
        }
    }

ManualResetEvent 类示例:

    class Program
    {
        private static ManualResetEvent resetEvent = new ManualResetEvent(false);
        static void Main(string[] args)
        {
            new Thread(DoOne).Start();
            // 用于不断向另一个线程发送信号
            while (true)
            {
                Console.ReadKey();
                resetEvent.Set();           // 发生通知,设置终止状态
            }
        }

        public static void DoOne()
        {
            Console.WriteLine("等待中,请发出信号允许我运行");
            resetEvent.WaitOne();

            // 后面的都无效,线程会直接跳过而无需等待
            resetEvent.WaitOne();
            resetEvent.WaitOne();
            resetEvent.WaitOne();
            resetEvent.WaitOne();
            resetEvent.WaitOne();
            Console.WriteLine("线程结束");
        }
    }

因为 AutoResetEvent 对象在 .WaitOne() 方法等待信号完毕后,会自动重置为非终止状态,相当于高速收费站自动闸门,一辆车过去后,机器自动关闸。

ManualResetEvent 相当于人工闸门,打开后编写人工关闭闸门,不然的话闸门会一直处于打开状态。

ManualResetEvent 主要用于更加灵活的线程信号传递场景。

ManualResetEvent 类

表示线程同步事件,收到信号时,要想下一次依然生效,必须手动重置该事件。

因为 ManualResetEvent 类跟 AutoManualResetEvent 类十分接近,这里就不赘述了。

它们的使用区别主要是:

AutoResetEvent 类,每次 Set() ,跳过一个 WaitOne()。因为会 自动恢复设置,所以下次碰到 WaitOne() 会继续等待。

ManualResetEvent 类, Set() 后,不会重置设置,因此一旦使用了 Set() 后,就会一路放通,不会再等待。

其构造函数如下:

构造函数 说明
ManualResetEvent(Boolean) 用一个指示是否将初始状态设置为终止的布尔值初始化 ManualResetEvent 类的新实例。

其常用方法如下:

方法 说明
Close() 释放由当前 WaitHandle 占用的所有资源。
Reset() 将事件状态设置为非终止,从而导致线程受阻。
Set() 将事件状态设置为有信号,从而允许一个或多个等待线程继续执行。
WaitOne() 阻止当前线程,直到当前 WaitHandle 收到信号。
WaitOne(Int32) 阻止当前线程,直到当前 WaitHandle 收到信号,同时使用 32 位带符号整数指定时间间隔(以毫秒为单位)。
WaitOne(Int32, Boolean) 阻止当前线程,直到当前的 WaitHandle 收到信号为止,同时使用 32 位带符号整数指定时间间隔,并指定是否在等待之前退出同步域。
WaitOne(TimeSpan) 阻止当前线程,直到当前实例收到信号,同时使用 TimeSpan 指定时间间隔。
WaitOne(TimeSpan, Boolean) 阻止当前线程,直到当前实例收到信号为止,同时使用 TimeSpan 指定时间间隔,并指定是否在等待之前退出同步域。

ManualResetEventSlim

ManualResetEventSlim 相对 ManualResetEvent ,当等待时间预计非常短并且事件不跨越进程边界时,可以使用此类来获得比 ManualResetEvent 更好的性能。

从代码使用来看,没有啥区别,主要就是考虑性能下时,两者不同场景。

这里就不对这两个类型赘述了。

到此这篇关于C#多线程系列之手动线程通知的文章就介绍到这了。希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • C#多线程系列之原子操作

    目录 知识点 竞争条件 线程同步 CPU时间片和上下文切换 阻塞 内核模式和用户模式 Interlocked 类 1,出现问题 2,Interlocked.Increment() 3,Interlocked.Exchange() 4,Interlocked.CompareExchange() 5,Interlocked.Add() 6,Interlocked.Read() 知识点 竞争条件 当两个或两个以上的线程访问共享数据,并且尝试同时改变它时,就发生争用的情况.它们所依赖的那部分共享数据,叫

  • C#多线程系列之进程同步Mutex类

    Mutex 中文为互斥,Mutex 类叫做互斥锁.它还可用于进程间同步的同步基元. Mutex 跟 lock 相似,但是 Mutex 支持多个进程.Mutex 大约比 lock 慢 20 倍. 互斥锁(Mutex),用于多线程中防止两条线程同时对一个公共资源进行读写的机制. Windows 操作系统中,Mutex 同步对象有两个状态: signaled:未被任何对象拥有: nonsignaled:被一个线程拥有: Mutex 只能在获得锁的线程中,释放锁. 构造函数和方法 Mutex 类其构造函

  • C#多线程系列之线程通知

    AutoRestEvent 类用于从一个线程向另一个线程发送通知. 微软文档是这样介绍的:表示线程同步事件在一个等待线程释放后收到信号时自动重置. 其构造函数只有一个: 构造函数里面的参数用于设置信号状态. 构造函数 说明 AutoResetEvent(Boolean) 用一个指示是否将初始状态设置为终止的布尔值初始化 AutoResetEvent 类的新实例. 真糟糕的机器翻译. 常用方法 AutoRestEvent 类是干嘛的,构造函数的参数又是干嘛的?不着急,我们来先来看看这个类常用的方法

  • C#多线程系列之多线程锁lock和Monitor

    目录 1,Lock lock 原型 lock 编写实例 2,Monitor 怎么用呢 解释一下 示例 设置获取锁的时效 1,Lock lock 用于读一个引用类型进行加锁,同一时刻内只有一个线程能够访问此对象.lock 是语法糖,是通过 Monitor 来实现的. Lock 锁定的对象,应该是静态的引用类型(字符串除外). 实际上字符串也可以作为锁的对象使用,只是由于字符串对象的特殊性,可能会造成不同位置的不同线程冲突.如果你能保证字符串的唯一性,例如 Guid 生成的字符串,也是可以作为锁的对

  • C#多线程系列之线程的创建和生命周期

    目录 1,获取当前线程信息 2,管理线程状态 2.1 启动与参数传递 2.1.1 ParameterizedThreadStart 2.1.2 使用静态变量或类成员变量 2.1.3 委托与Lambda 2.2 暂停与阻塞 2.3 线程状态 2.4 终止 2.5 线程的不确定性 2.6 线程优先级.前台线程和后台线程 2.7 自旋和休眠 1,获取当前线程信息 Thread.CurrentThread 是一个 静态的 Thread 类,Thread 的CurrentThread 属性,可以获取到当前

  • C#多线程系列之资源池限制

    Semaphore.SemaphoreSlim 类 两者都可以限制同时访问某一资源或资源池的线程数. 这里先不扯理论,我们从案例入手,通过示例代码,慢慢深入了解. Semaphore 类 这里,先列出 Semaphore 类常用的 API. 其构造函数如下: 构造函数 说明 Semaphore(Int32, Int32) 初始化 Semaphore 类的新实例,并指定初始入口数和最大并发入口数. Semaphore(Int32, Int32, String) 初始化 Semaphore 类的新实

  • C#多线程系列之多阶段并行线程

    前言 这一篇,我们将学习用于实现并行任务.使得多个线程有序同步完成多个阶段的任务. 应用场景主要是控制 N 个线程(可随时增加或减少执行的线程),使得多线程在能够在 M 个阶段中保持同步. 线程工作情况如下: 我们接下来 将学习C# 中的 Barrier ,用于实现并行协同工作. Barrier 类 使多个任务能够采用并行方式依据某种算法在多个阶段中协同工作,使多个线程(称为“参与者” )分阶段同时处理算法. 可以使多个线程(称为“参与者” )分阶段同时处理算法.(注意算法这个词) 每个参与者完

  • C#多线程系列之线程完成数

    解决一个问题 假如,程序需要向一个 Web 发送 5 次请求,受网路波动影响,有一定几率请求失败.如果失败了,就需要重试. 示例代码如下: class Program { private static int count = 0; static void Main(string[] args) { for (int i = 0; i < 5; i++) new Thread(HttpRequest).Start(); // 创建线程 // 用于不断向另一个线程发送信号 while (count

  • C#多线程系列之手动线程通知

    区别与示例 AutoResetEvent 和 ManualResetEvent 十分相似.两者之间的区别,在于前者是自动(Auto),后者是手动(Manua). 你可以先运行下面的示例,再测试两者的区别. AutoResetEvent 示例: class Program { // 线程通知 private static AutoResetEvent resetEvent = new AutoResetEvent(false); static void Main(string[] args) {

  • C#多线程系列之线程池

    目录 线程池 ThreadPool 常用属性和方法 线程池说明和示例 线程池线程数 线程池线程数说明 不支持的线程池异步委托 任务取消功能 计时器 线程池 线程池全称为托管线程池,线程池受 .NET 通用语言运行时(CLR)管理,线程的生命周期由 CLR 处理,因此我们可以专注于实现任务,而不需要理会线程管理. 线程池的应用场景:任务并行库 (TPL)操作.异步 I/O 完成.计时器回调.注册的等待操作.使用委托的异步方法调用和套接字连接. 很多人不清楚 Task.Task<TResult>

  • C#多线程系列之线程等待

    目录 前言 volatile 关键字 三种常用等待 再说自旋和阻塞 SpinWait 结构 属性和方法 自旋示例 新的实现 SpinLock 结构 属性和方法 示例 等待性能对比 前言 volatile 关键字 volatile 关键字指示一个字段可以由多个同时执行的线程修改. 我们继续使用<C#多线程(3):原子操作>中的示例: static void Main(string[] args) { for (int i = 0; i < 5; i++) { new Thread(AddO

  • C#多线程系列之任务基础(一)

    目录 多线程编程 多线程编程模式 探究优点 任务操作 两种创建任务的方式 Task.Run() 创建任务 取消任务 父子任务 任务返回结果以及异步获取返回结果 捕获任务异常 全局捕获任务异常 多线程编程 多线程编程模式 .NET 中,有三种异步编程模式,分别是基于任务的异步模式(TAP).基于事件的异步模式(EAP).异步编程模式(APM). 基于任务的异步模式 (TAP) :.NET 推荐使用的异步编程方法,该模式使用单一方法表示异步操作的开始和完成.包括我们常用的 async .await

  • 聊聊java多线程创建方式及线程安全问题

    什么是线程 线程被称为轻量级进程,是程序执行的最小单位,它是指在程序执行过程中,能够执行代码的一个执行单位.每个程序程序都至少有一个线程,也即是程序本身. 线程的状态 新建(New):创建后尚未启动的线程处于这种状态 运行(Runable):Runable包括了操作系统线程状态的Running和Ready,也就是处于此状态的线程有可能正在执行,也有可能正在等待着CPU为它分配执行时间. 等待(Wating):处于这种状态的线程不会被分配CPU执行时间.等待状态又分为无限期等待和有限期等待,处于无

随机推荐