C#中ManualResetEvent 和 ManualResetEventSlim的使用

2023-10-24 01:45

本文主要是介绍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();}}
}

 

这篇关于C#中ManualResetEvent 和 ManualResetEventSlim的使用的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/271886

相关文章

使用Java将DOCX文档解析为Markdown文档的代码实现

《使用Java将DOCX文档解析为Markdown文档的代码实现》在现代文档处理中,Markdown(MD)因其简洁的语法和良好的可读性,逐渐成为开发者、技术写作者和内容创作者的首选格式,然而,许多文... 目录引言1. 工具和库介绍2. 安装依赖库3. 使用Apache POI解析DOCX文档4. 将解析

Qt中QUndoView控件的具体使用

《Qt中QUndoView控件的具体使用》QUndoView是Qt框架中用于可视化显示QUndoStack内容的控件,本文主要介绍了Qt中QUndoView控件的具体使用,具有一定的参考价值,感兴趣的... 目录引言一、QUndoView 的用途二、工作原理三、 如何与 QUnDOStack 配合使用四、自

C++使用printf语句实现进制转换的示例代码

《C++使用printf语句实现进制转换的示例代码》在C语言中,printf函数可以直接实现部分进制转换功能,通过格式说明符(formatspecifier)快速输出不同进制的数值,下面给大家分享C+... 目录一、printf 原生支持的进制转换1. 十进制、八进制、十六进制转换2. 显示进制前缀3. 指

C#中async await异步关键字用法和异步的底层原理全解析

《C#中asyncawait异步关键字用法和异步的底层原理全解析》:本文主要介绍C#中asyncawait异步关键字用法和异步的底层原理全解析,本文给大家介绍的非常详细,对大家的学习或工作具有一... 目录C#异步编程一、异步编程基础二、异步方法的工作原理三、代码示例四、编译后的底层实现五、总结C#异步编程

使用Python构建一个Hexo博客发布工具

《使用Python构建一个Hexo博客发布工具》虽然Hexo的命令行工具非常强大,但对于日常的博客撰写和发布过程,我总觉得缺少一个直观的图形界面来简化操作,下面我们就来看看如何使用Python构建一个... 目录引言Hexo博客系统简介设计需求技术选择代码实现主框架界面设计核心功能实现1. 发布文章2. 加

C#TextBox设置提示文本方式(SetHintText)

《C#TextBox设置提示文本方式(SetHintText)》:本文主要介绍C#TextBox设置提示文本方式(SetHintText),具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑... 目录C#TextBox设置提示文本效果展示核心代码总结C#TextBox设置提示文本效果展示核心代

shell编程之函数与数组的使用详解

《shell编程之函数与数组的使用详解》:本文主要介绍shell编程之函数与数组的使用,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录shell函数函数的用法俩个数求和系统资源监控并报警函数函数变量的作用范围函数的参数递归函数shell数组获取数组的长度读取某下的

使用Python开发一个带EPUB转换功能的Markdown编辑器

《使用Python开发一个带EPUB转换功能的Markdown编辑器》Markdown因其简单易用和强大的格式支持,成为了写作者、开发者及内容创作者的首选格式,本文将通过Python开发一个Markd... 目录应用概览代码结构与核心组件1. 初始化与布局 (__init__)2. 工具栏 (setup_t

C#中DrawCurve的用法小结

《C#中DrawCurve的用法小结》本文主要介绍了C#中DrawCurve的用法小结,通常用于绘制一条平滑的曲线通过一系列给定的点,具有一定的参考价值,感兴趣的可以了解一下... 目录1. 如何使用 DrawCurve 方法(不带弯曲程度)2. 如何使用 DrawCurve 方法(带弯曲程度)3.使用Dr

Python虚拟环境终极(含PyCharm的使用教程)

《Python虚拟环境终极(含PyCharm的使用教程)》:本文主要介绍Python虚拟环境终极(含PyCharm的使用教程),具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,... 目录一、为什么需要虚拟环境?二、虚拟环境创建方式对比三、命令行创建虚拟环境(venv)3.1 基础命令3