iis服务器助手广告广告
返回顶部
首页 > 资讯 > 后端开发 > 其他教程 >C#多线程系列之线程通知
  • 236
分享到

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

2024-04-02 19:04:59 236人浏览 独家记忆
摘要

AutoRestEvent 类用于从一个线程向另一个线程发送通知。 微软文档是这样介绍的:表示线程同步事件在一个等待线程释放后收到信号时自动重置。 其构造函数只有一个: 构造函数里面

AutoRestEvent 类用于从一个线程向另一个线程发送通知。

微软文档是这样介绍的:表示线程同步事件在一个等待线程释放后收到信号时自动重置。

其构造函数只有一个:

构造函数里面的参数用于设置信号状态。

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

真糟糕的机器翻译

常用方法

AutoRestEvent 类是干嘛的,构造函数的参数又是干嘛的?不着急,我们来先来看看这个类常用的方法:

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

一个简单的示例

这里我们编写一个这样的程序:

创建一个线程,能够执行多个阶段的任务;每完成一个阶段,都需要停下来,等待子线程发生通知,才能继续下一步执行。

.WaitOne() 用来等待另一个线程发送通知;

.Set() 用来对线程发出通知,此时 AutoResetEvent 变成终止状态;

.ReSet() 用来重置 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("\n     收到信号,继续执行");
            for (int i = 0; i < 5; i++) Thread.Sleep(TimeSpan.FromSeconds(0.5));

            resetEvent.Reset(); // 重置为非终止状态
            Console.WriteLine("\n第一阶段运行完毕,请继续给予指示");

            // 等待其它线程发送信号
            resetEvent.WaitOne();
            Console.WriteLine("\n     收到信号,继续执行");
            for (int i = 0; i < 5; i++) Thread.Sleep(TimeSpan.FromSeconds(0.5));

            Console.WriteLine("\n第二阶段运行完毕,线程结束,请手动关闭窗口");
        }
    }

解释一下

AutoResetEvent 对象有终止和非终止状态。Set() 设置终止状态,Reset() 重置非终止状态。

这个终止状态,可以理解成信号已经通知;非终止状态则是信号还没有通知。

注意,注意终止状态和非终止状态指的是 AutoResetEvent 的状态,不是指线程的状态。

线程通过调用 WaitOne() 方法,等待信号;
另一个线程可以调用 Set() 通知 AutoResetEvent 释放等待线程。
然后 AutoResetEvent 变为终止状态。

需要注意的是,如果 AutoResetEvent 已经处于终止状态,那么线程调用 WaitOne() 不会再起作用。除非调用Reset() 。

构造函数中的参数,正是设置这个状态的。true 代表终止状态,false 代表非终止状态。如果使用 new AutoResetEvent(true); ,则线程一开始是无需等待信号的。

在使用完类型后,您应直接或间接释放类型,显式调用 Close()/Dispose() 或 使用 using。 当然,也可以直接退出程序。

需要注意的是,如果多次调用 Set() 的时间间隔过短,如果第一次 Set() 还没有结束(信号发送需要处理时间),那么第二次 Set() 可能无效(不起作用)。

复杂一点的示例

我们设计一个程序:

  • Two 线程开始处于阻塞状态;
  • 线程 One 可以设置线程 Two 继续运行,然后阻塞自己;
  • 线程 Two 可以设置 One 继续运行,然后阻塞自己;

程序代码如下(运行后,请将键盘设置成英文输入状态再按下按键):

    class Program
    {
        // 控制第一个线程
        // 第一个线程开始时,AutoResetEvent 处于终止状态,无需等待信号
        private static AutoResetEvent oneResetEvent = new AutoResetEvent(true);

        // 控制第二个线程
        // 第二个线程开始时,AutoResetEvent 处于非终止状态,需要等待信号
        private static AutoResetEvent twoResetEvent = new AutoResetEvent(false);

        static void Main(string[] args)
        {
            new Thread(DoOne).Start();
            new Thread(DoTwo).Start();

            Console.ReadKey();
        }

        public static void DoOne()
        {
            while (true)
            {
                Console.WriteLine("\n① 按一下键,我就让DoTwo运行");
                Console.ReadKey();
                twoResetEvent.Set();
                oneResetEvent.Reset();
                // 等待 DoTwo() 给我信号
                oneResetEvent.WaitOne();

                Console.ForegroundColor = ConsoleColor.Green;
                Console.WriteLine("\n     DoOne() 执行");
                Console.ForegroundColor = ConsoleColor.White;
            }
        }

        public static void DoTwo()
        {
            while (true)
            {
                Thread.Sleep(TimeSpan.FromSeconds(1));

                // 等待 DoOne() 给我信号
                twoResetEvent.WaitOne();

                Console.ForegroundColor = ConsoleColor.Yellow;
                Console.WriteLine("\n     DoTwo() 执行");
                Console.ForegroundColor = ConsoleColor.White;

                Console.WriteLine("\n② 按一下键,我就让DoOne运行");
                Console.ReadKey();
                oneResetEvent.Set();
                twoResetEvent.Reset();
            }
        }
    }

解释

两个线程具有的功能:阻塞自己、解除另一个线程的阻塞。

用电影《最佳拍档》里面的一个画面来理解。

DoOne 、DoTwo 轮流呼吸,不能自己控制自己呼吸,但自己能够决定别人呼吸。

你搞我,我搞你,就能相互呼吸了。

当然WaitOne() 也可以设置等待时间,如果 光头佬(DoOne) 耍赖不让 金刚(DoTwo)呼吸,金刚等待一定时间后,可以强行荡动天平,落地呼吸。

注意,AutoRestEvent 用得不当容易发生死。 
另外 AutoRestEvent 使用的是内核时间模式,因此等待时间不能太长,不然比较耗费 CPU 时间。

AutoResetEvent 也适合用于线程同步。

另外,线程中使用 WaitOne() ,另一个线程使用 Set() 通知后, AutoResetEvent 对象会自动恢复非终止状态,不需要线程使用 Reset() 。

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

--结束END--

本文标题: C#多线程系列之线程通知

本文链接: https://www.lsjlt.com/news/139007.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • C#多线程系列之线程通知
    AutoRestEvent 类用于从一个线程向另一个线程发送通知。 微软文档是这样介绍的:表示线程同步事件在一个等待线程释放后收到信号时自动重置。 其构造函数只有一个: 构造函数里面...
    99+
    2024-04-02
  • C#多线程系列之手动线程通知
    区别与示例 AutoResetEvent 和 ManualResetEvent 十分相似。两者之间的区别,在于前者是自动(Auto),后者是手动(Manua)。 你可以先运行下面的示...
    99+
    2024-04-02
  • C#多线程系列之线程池
    目录线程池ThreadPool 常用属性和方法线程池说明和示例线程池线程数线程池线程数说明不支持的线程池异步委托任务取消功能计时器线程池 线程池全称为托管线程池,线程池受 .NET ...
    99+
    2024-04-02
  • C#多线程系列之线程等待
    目录前言volatile 关键字三种常用等待再说自旋和阻塞SpinWait 结构属性和方法自旋示例新的实现SpinLock 结构属性和方法示例等待性能对比前言 volatile 关键...
    99+
    2024-04-02
  • C#多线程系列之线程完成数
    解决一个问题 假如,程序需要向一个 Web 发送 5 次请求,受网路波动影响,有一定几率请求失败。如果失败了,就需要重试。 示例代码如下: class Program ...
    99+
    2024-04-02
  • C#多线程系列之多线程锁lock和Monitor
    目录1,Locklock 原型lock 编写实例2,Monitor怎么用呢解释一下示例设置获取锁的时效1,Lock lock 用于读一个引用类型进行加锁,同一时刻内只有一个线程能够访...
    99+
    2024-04-02
  • C#多线程系列之多阶段并行线程
    前言 这一篇,我们将学习用于实现并行任务、使得多个线程有序同步完成多个阶段的任务。 应用场景主要是控制 N 个线程(可随时增加或减少执行的线程),使得多线程在能够在 M 个阶段中保持...
    99+
    2024-04-02
  • C#多线程之线程通讯(AutoResetEvent)
    一、简介 我们在线程编程的时候往往会涉及到线程的通信,通过信号的接受来进行线程是否阻塞的操作。AutoResetEvent 允许线程通过发信号互相通信。通常,此通信涉及线程需要独占访...
    99+
    2024-04-02
  • C#多线程系列之读写锁
    本篇的内容主要是介绍 ReaderWriterLockSlim 类,来实现多线程下的读写分离。 ReaderWriterLockSlim ReaderWriterLock 类:定义支...
    99+
    2024-04-02
  • C#多线程系列之原子操作
    目录知识点竞争条件线程同步CPU时间片和上下文切换阻塞内核模式和用户模式Interlocked类1,出现问题2,Interlocked.Increment()3,Interlocke...
    99+
    2024-04-02
  • C#多线程系列之进程同步Mutex类
    Mutex 中文为互斥,Mutex 类叫做互斥锁。它还可用于进程间同步的同步基元。 Mutex 跟 lock 相似,但是 Mutex 支持多个进程。Mutex 大约比 lock 慢 ...
    99+
    2024-04-02
  • C#多线程系列之线程的创建和生命周期
    目录1,获取当前线程信息2,管理线程状态2.1启动与参数传递2.1.1ParameterizedThreadStart2.1.2使用静态变量或类成员变量2.1.3委托与Lambda2...
    99+
    2024-04-02
  • C#多线程之线程锁
    目录一、Mutex类二、Mutex的用途三、Semaphore信号量1、简介2、初始化3、WaitOne()和Release()四、Monitor类典型的生产者与消费者实例五、Loc...
    99+
    2024-04-02
  • C#多线程系列之资源池限制
    Semaphore、SemaphoreSlim 类 两者都可以限制同时访问某一资源或资源池的线程数。 这里先不扯理论,我们从案例入手,通过示例代码,慢慢深入了解。 Semaphore...
    99+
    2024-04-02
  • C#多线程系列之任务基础(二)
    目录判断任务状态再说父子任务组合任务/延续任务复杂的延续任务并行(异步)处理任务并行(同步)处理任务并行任务的 Task.WhenAny并行任务状态循环中值变化问题定时任务 Task...
    99+
    2024-04-02
  • C#多线程系列之任务基础(三)
    目录TaskAwaiter延续的另一种方法另一种创建任务的方法实现一个支持同步和异步任务的类型Task.FromCanceled()如何在内部取消任务Yield 关键字补充知识点Ta...
    99+
    2024-04-02
  • C#多线程系列之工作流实现
    目录前言节点ThenParallelScheduleDelay试用一下顺序节点并行任务编写工作流接口构建器工作流构建器依赖注入实现工作流解析前言 前面学习了很多多线程和任务的基础知识...
    99+
    2024-04-02
  • C#多线程系列之任务基础(一)
    目录多线程编程多线程编程模式探究优点任务操作两种创建任务的方式Task.Run() 创建任务取消任务父子任务任务返回结果以及异步获取返回结果捕获任务异常全局捕获任务异常多线程编程 多...
    99+
    2024-04-02
  • C#多线程之线程池(ThreadPool)
    一、简介 前面介绍了平时用到的大多数的多线程的例子,但在实际开发中使用的线程往往是大量的和更为复杂的,这时,每次都创建线程、启动线程。从性能上来讲,这样做并不理想(因为每使用一个线程...
    99+
    2024-04-02
  • C#多线程之线程同步
    一、前言 我们先来看下面一个例子: using System; using System.Threading; namespace ThreadSynchDemo { cl...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作