C#中ManualResetEvent 和 ManualResetEventSlim的使用

从 .NET Framework 版本2.0 开始, ManualResetEvent 派生自 EventWaitHandle 类。 在 ManualResetEvent 功能上等效于EventWaitHandle 使用创建的EventResetMode.ManualReset。ManualResetEventSlim用于实现更好的性能 ManualResetEvent。以下介绍.NET(C#)中ManualResetEvent 和 ManualResetEventSlim的使用总结。

 

1、ManualResetEvent 和 ManualResetEventSlim

ManualResetEvent表示线程同步事件,收到信号时,必须手动重置该事件。 此类不能被继承。ManualResetEventSlim于实现更好的性能 ManualResetEvent ,而不是等待时间预计非常短,事件不会跨越进程边界。 等待事件收到信号期间,ManualResetEventSlim 会短暂使用忙碌旋转。 等待时间较短时,旋转的开销相对于使用等待句柄来进行等待的开销会少很多。 不过,如果在特定时间段内事件没有收到信号,ManualResetEventSlim 会求助于常规的事件句柄等待。从 .NET Framework 版本4.0 开始, System.Threading.ManualResetEventSlim 类是的轻型替代ManualResetEvent

2、ManualResetEvent的使用

参考文档:ManualResetEvent 类 (System.Threading) | Microsoft Learn

new ManualResetEvent(false)为创建在无信号状态。WaitOne()方法会阻塞,调用Set()方法设置为有信号状态,WaitOne()方法不会阻塞,需要调用Reset()方法变为无信号状态,WaitOne()方法将会阻塞。new ManualResetEvent(true)为创建在有信号状态。WaitOne()方法不会阻塞,需要调用Reset()方法变为无信号状态,WaitOne()方法将会阻塞。

例如,

using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
namespace ConsoleApplication
{class Program{mre用于手动阻塞和释放线程。false是创建在无信号状态。private static ManualResetEvent mre = new ManualResetEvent(false);static void Main(){Console.WriteLine("启动 3个在ManualResetEvent上阻塞的命名线程");for (int i = 0; i <= 2; i++){Thread t = new Thread(ThreadProc);t.Name = "Thread_" + i;t.Start();}Thread.Sleep(500);Console.WriteLine("按回车键,当三个线程都启动后,调用Set()释放所有线程。");Console.ReadLine();mre.Set();Thread.Sleep(500);Console.WriteLine("按回车键,当ManualResetEvent有信号时,调用WaitOne()的线程不会阻塞。");Console.ReadLine();for (int i = 3; i <= 4; i++){Thread t = new Thread(ThreadProc);t.Name = "Thread_" + i;t.Start();}Thread.Sleep(500);Console.WriteLine("按回车键,调用Reset(),这样线程在调用WaitOne()时就会再次阻塞。");Console.ReadLine();mre.Reset();// Start a thread that waits on the ManualResetEvent.Thread t5 = new Thread(ThreadProc);t5.Name = "Thread_5";t5.Start();Thread.Sleep(500);Console.WriteLine("按回车键,调用Set()并结束运行。");Console.ReadLine();mre.Set();// 如在Visual Studio中运行这个例子,取消下面这行注释://Console.ReadLine();}private static void ThreadProc(){string name = Thread.CurrentThread.Name;Console.WriteLine(name + " 调用 mre.WaitOne()");mre.WaitOne();Console.WriteLine(name + " 结束");}}
}

 

3、ManualResetEventSlim的使用

参考文档:ManualResetEventSlim 类 (System.Threading) | Microsoft Learn

new ManualResetEventSlim(false)为创建在无信号状态。Wait()方法会阻塞,调用Set()方法设置为有信号状态,Wait()方法不会阻塞,需要调用Reset()方法变为无信号状态,Wait()方法将会阻塞。new ManualResetEventSlim(true)为创建在有信号状态。Wait()方法不会阻塞,需要调用Reset()方法变为无信号状态,Wait()方法将会阻塞。

例如,

using System;
using System.Threading;
using System.Threading.Tasks;
namespace ConsoleApplication
{class Program{static void Main(){MRES_SetWaitReset();MRES_SpinCountWaitHandle();}// //      ManualResetEventSlim construction//      ManualResetEventSlim.Wait()//      ManualResetEventSlim.Set()//      ManualResetEventSlim.Reset()//      ManualResetEventSlim.IsSetstatic void MRES_SetWaitReset(){ManualResetEventSlim mres1 = new ManualResetEventSlim(false); // 初始创建为无信号状态ManualResetEventSlim mres2 = new ManualResetEventSlim(false); // 初始创建为无信号状态ManualResetEventSlim mres3 = new ManualResetEventSlim(true);  // 初始创建为有信号状态// 启动一个操作mres3和mres2的异步任务var observer = Task.Factory.StartNew(() =>{mres1.Wait();Console.WriteLine("observer mres1 信号");Console.WriteLine("observer Reset mres3 信号");mres3.Reset(); // mres3 应该无信号Console.WriteLine("observer Set mres2");mres2.Set();});Console.WriteLine("主线程: mres3.IsSet = {0} (应该为true)", mres3.IsSet);Console.WriteLine("主线程 Set mres1");mres1.Set(); // 将会执行 observer Taskmres2.Wait(); // observer Task完成Reset mres3,Set mres2Console.WriteLine("主线程 mres2 有信号");Console.WriteLine("主线程: mres3.IsSet = {0} (应该为false)", mres3.IsSet);// 用完ManualResetEventSlim时,Dispose()一个ManualResetEventSlim释放资源observer.Wait(); // 确保observer执行完成mres1.Dispose();mres2.Dispose();mres3.Dispose();// 如在Visual Studio中运行这个例子,取消下面这行注释:Console.ReadLine();}// ://      ManualResetEventSlim construction w/ SpinCount//      ManualResetEventSlim.WaitHandlestatic void MRES_SpinCountWaitHandle(){// 构造一个SpinCount为1000的ManualResetEventSlimManualResetEventSlim mres1 = new ManualResetEventSlim(false, 1000);ManualResetEventSlim mres2 = new ManualResetEventSlim(false, 1000);Task bgTask = Task.Factory.StartNew(() =>{// Just wait a littleThread.Sleep(100);// 给两个MRESes发信号Console.WriteLine("mres1.Set() mres2.Set()");mres1.Set();mres2.Set();});//等待指定数组中的所有元素都收到信号。WaitHandle.WaitAll(new WaitHandle[] { mres1.WaitHandle, mres2.WaitHandle });Console.WriteLine("WaitHandle.WaitAll(mres1.WaitHandle, mres2.WaitHandle) completed.");// Clean upbgTask.Wait();mres1.Dispose();mres2.Dispose();}}
}

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/116036.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

导航守卫和拦截器

导航守卫 1.全局守卫 &#xff1a; 全局前置守卫&#xff08;beforeEach&#xff09;&#xff0c;分别有三个参数to,form,next 使用场景&#xff1a;全局前置守卫是最常用的导航守卫&#xff0c;它主要作用于登录验证&#xff0c;获取用户权限信息等场景。 全局后置守卫&am…

ElasticSearch Java API GEO操作(REST命令版)

前言 ElasticSearch支持地理空间数据查询、搜索&#xff0c;提供geo_point、geo_shape两种地理数据类型。 geo_point用于描述一个或多个地理坐标点&#xff0c;主要用于周边位置查询、边界内搜索点、聚合多个范围内的点等功能。 geo_shape用于描述点线面等多种地理数据&…

DS森林叶子编码/森林转二叉树 【数据结构】

DS森林叶子编码 题目描述 给定一组森林&#xff0c;编写程序生成对应的二叉树&#xff0c;输出这颗二叉树叶结点对应的二进制编码.规定二叉树的左边由0表示&#xff0c;二叉树的右边由1表示。 输入 N B 表示N个树&#xff0c;每结点最多B个分支 第2行至第N1行&#xff0c;每个…

驱动开发day1

头文件 #ifndef __HEAD_H__ #define __HEAD_H__ #define PHY_LED1_MODER 0X50006000 #define PHY_LED1_ODR 0X50006014#define PHY_LED2_MODER 0x50007000 #define PHY_LED2_ODR 0x50007014#define PHY_LED3_MODER 0x50006000 #define PHY_LED3_ODR 0x50006014#define P…

电脑技巧:27个Office使用小技巧,值得收藏

目录 一、Word 二、EXCEL 三、附文&#xff1a;Word和Excel快捷键 我们中的绝大部分人都使用微软的Office&#xff0c;但是我们是否都了解如何能够最有效地使用它&#xff1f;我们在这里列举了一些关于使用Word和Excel的窍门。 我们使用最多的软件可能就是办公软件了——字…

思辨:移动开发的未来在哪?

前段时间在知乎看到关于移动开发未来的问题&#xff0c;就尝试回答了一下&#xff0c;也触发了我对移动开发未来的思考。 什么是移动开发&#xff1f; 我们口中说的移动开发是什么&#xff0c;从广义和狭义的角度分别来看下&#xff1a; 从广义角度来看&#xff0c;移动开发是…

BMS电池管理系统理论基础

目录 1 、锂离子电池特性分析 1.1、 锂离子电池工作原理 1.2 锂离子电池特性 (1)容量特性

安装zip扩展(PHP)

记录一次 安装zip扩展的最优方案 &#xff08;备注 网上以及Ai提供的很乱不能很快解决&#xff09; 首先搜索zip包 yum search zip选择自己合适的php版本 比如我的php是7.4.33的 我就用php74-php-pecl-zip 如果没有的话 先添加软件源 sudo yum install epel-release sudo yu…

docker-rabbitmq 安装依赖

出现的问题如下: channel error; protocol method: #method(reply-code404, reply-textNOT_FOUND - no channel error&#xff1b; protocol method: #method&#xff1c;channel.close&#xff1e;(reply-code404, reply-textNOT_FOUND - no 查看rabbitmq 客户端是否存在如…

Kubernetes - 一键安装部署 K8S(附:Kubernetes Dashboard)

问题描述 不知道大伙是如何安装 K8s&#xff0c;特别还是集群的时候&#xff0c;我上一次安装搭建的时候&#xff0c;那个恶心到我了&#xff0c;真的是一步一个脚印走完整个搭建流程&#xff0c;爬了不少坑。 于是&#xff0c;才有了今天的文章&#xff0c;到底有没有可以一…

Kafka快速入门(最新版3.6.0)

文章目录 一、初识MQ1.1 什么是MQ1.2 同步和异步通讯1.1.1 同步通讯1.1.2 异步通讯 1.3 技术对比1.4 MQ的两种模式 二、初识Kafka2.1 Kafka的使用场景2.2 Kafka基本概念2.3 Topic与Partition 三、Kafka基本使用3.1 部署前的准备3.2 启动kafka服务器3.3 Kafka核心概念之Topic3.4…

出差学小白知识No6:LD_PRELOAD变量路径不对找不到库文件

交叉编译的时候出现以下问题&#xff0c;显示LD_PRELOAD变量找不到路劲 首先先查看一下LD_PRELOAD的路径&#xff1a;echo $LD_PRELOAD 如果输出一大串&#xff0c;那么先进行清空&#xff1a;unset LD_PRELOAD 重新给LD_PRELOAD进行赋值他的路径和库文件&#xff1a; expor…

操作系统【OS】Ch2 大题 PV题型分类

生产者-消费者问题&#xff1a;生产资源-消费资源理发师问题&#xff1a;服务-被服务读者-写者问题&#xff1a;同类进程不互斥、异类进程互斥哲学家进餐问题&#xff1a;只有一类进程&#xff0c;每个进程需要同时拥有多种资源才能运行单纯的同步问题&#xff1a;前驱后继图 生…

自然语言处理---RNN经典案例之构建人名分类器

1 案例介绍 关于人名分类问题&#xff1a;以一个人名为输入, 使用模型帮助判断它最有可能是来自哪一个国家的人名&#xff0c;这在某些国际化公司的业务中具有重要意义&#xff0c;在用户注册过程中&#xff0c;会根据用户填写的名字直接给他分配可能的国家或地区选项&#xff…

【第三天】C++类和对象进阶指南:从堆区空间操作到友元的深度掌握

一、new和delete 堆区空间操作 1、new和delete操作基本类型的空间 new与C语言中malloc、delete和C语言中free 作用基本相同 区别&#xff1a; new 不用强制类型转换 new在申请空间的时候可以 初始化空间内容 2、 new申请基本类型的数组 3、new和delete操作类的空间 4、new申请…

为什么需要it企业知识库?it企业知识库能带来什么?

在企业运营过程中&#xff0c;会产生大量的经营数据、管理规范、资料和文档等数据&#xff0c;但这些数据的产生时间和空间碎片化&#xff0c;数据来源和结构多种多样&#xff0c;信息关系也较为复杂。 it企业知识库 正是因为这些问题的存在&#xff0c;导致了企业信息管理零散…

数据迁移一致性测试探索与实践

背景 量级庞大的日志通过mysql不足以支撑业务需求&#xff0c;以前通过任务调度定时跑批从mysql同步到hive存储&#xff0c;这种方式时效性为T1&#xff0c;也就是说今天的日志&#xff0c;明天才能同步到hive&#xff0c;总而言之时效性不高。为了提高时效性&#xff0c;改为…

【word技巧】word页眉,如何禁止他人修改?

我们设置了页眉内容之后&#xff0c;不想其他人修改自己的页眉内容&#xff0c;我们可以设置加密的&#xff0c;设置方法如下&#xff1a; 先将页眉设置好&#xff0c;退出页眉设置之后&#xff0c;我们选择布局功能&#xff0c;点击分隔符 – 连续 设置完之后页面分为上下两节…

shell_42.Linux移动参数

移动参数 bash shell 工具箱中的另一件工具是 shift 命令&#xff0c;该命令可用于操作命令行参数。跟字面上的意思一样&#xff0c;shift 命令会根据命令行参数的相对位置进行移动。 在使用 shift 命令时&#xff0c;默认情况下会将每个位置的变量值都向左移动一个位置。因此&…

JVM内存耗尽应用卡死分析

一个应用程序卡死了&#xff0c;查看JVM内存耗尽了&#xff0c;该做些什么呢? &#xff08;1&#xff09;整体资源查看 top命令&#xff0c;查看内存、CPU使用情况是否有明显问题。 &#xff08;2&#xff09;查看网络连接数 netstat -an | wc -l &#xff08;3&#xff0…