博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【AutoResetEvent】
阅读量:5050 次
发布时间:2019-06-12

本文共 4710 字,大约阅读时间需要 15 分钟。

AutoResetEvent用于线程间的同步

Test.cs代码:

class Test

{
//构造函数,用一个指示是否将初始状态设置为终止的布尔值初始化该类的新实例。
//false:无信号,子线程的WaitOne方法不会被自动调用
//true:有信号,子线程的WaitOne方法会被自动调用

//在.Net多线程编程中,AutoResetEvent和ManualResetEvent这两个类经常用到, 他们的用法很类似,但也有区别。Set方法将信号置为发送状态,Reset方法将信号置为不发送状态,WaitOne等待信号的发送。可以通过构造函数的参数值来决定其初始状态,若为true则非阻塞状态,为false为阻塞状态。如果某个线程调用WaitOne方法,则当信号处于发送状态时,该线程会得到信号, 继续向下执行。其区别就在调用后,AutoResetEvent.WaitOne()每次只允许一个线程进入,当某个线程得到信号后,AutoResetEvent会自动又将信号置为不发送状态,则其他调用WaitOne的线程只有继续等待.也就是说,AutoResetEvent一次只唤醒一个线程;而ManualResetEvent则可以唤醒多个线程,因为当某个线程调用了ManualResetEvent.Set()方法后,其他调用WaitOne的线程获得信号得以继续执行,而ManualResetEvent不会自动将信号置为不发送。也就是说,除非手工调用了ManualResetEvent.Reset()方法,则ManualResetEvent将一直保持有信号状态,ManualResetEvent也就可以同时唤醒多个线程继续执行。

//本质上AutoResetEvent.Set()方法相当于ManualResetEvent.Set()+ManualResetEvent.Reset();

//因此AutoResetEvent一次只能唤醒一个线程,其他线程还是堵塞
private static AutoResetEvent _workerEvent = new AutoResetEvent(false);
private static AutoResetEvent _mainEvent = new AutoResetEvent(false);

static void Process(int seconds)

{
Console.WriteLine("②子线程开始长时间运行的工作...");
Thread.Sleep(TimeSpan.FromSeconds(seconds));
Console.WriteLine("③子线程工作完成!");
_workerEvent.Set();

//--------------------------------------------------------

Console.WriteLine("④等待主线程完成其工作");

_mainEvent.WaitOne();

//--------------------------------------------------------

Console.WriteLine("⑧子线程开始第二个操作...");

Thread.Sleep(TimeSpan.FromSeconds(seconds));
Console.WriteLine("⑨子线程第二个操作工作完成!");
//这里是设置为有信号
_workerEvent.Set();
}

//简单来说只有调用Set()方法后才能执行WaitOne()后面的代码,AutoResetEvent和ManualResetEvent分别都有Set()改变为有信号 ,Reset()改变为无信号,WaitOne()将会阻塞当前调用的线程,直到有信号为止,即执行了Set()方法,WaitOne()方法还可以带指定时间的参数。
public static void RunTest()
{
//开启一个处理线程(子线程)
var t = new Thread((() => Process(10)));
t.Start();
Console.WriteLine("①等待一个子线程完成工作");
_workerEvent.WaitOne();
//--------------------------------------------------------

Console.WriteLine("⑤子线程第一个操作完成!");

Console.WriteLine("⑥在主线程上执行操作");
Thread.Sleep(TimeSpan.FromSeconds(5));
//主线程设置为有信号,即通知正在等待的线程有事件发生
_mainEvent.Set();
Console.WriteLine("⑦现在在子线程上运行第二个操作");

//--------------------------------------------------------

//执行到这个地方时,会等待set调用后改变了信号才接着执行

_workerEvent.WaitOne();
Console.WriteLine("⑩子线程第二个操作完成!");
//--------------------------------------------------------
Console.ReadKey();
}
}

class Test

{
//构造函数,用一个指示是否将初始状态设置为终止的布尔值初始化该类的新实例。
//false:无信号,子线程的WaitOne方法不会被自动调用
//true:有信号,子线程的WaitOne方法会被自动调用

//在.Net多线程编程中,AutoResetEvent和ManualResetEvent这两个类经常用到, 他们的用法很类似,但也有区别。Set方法将信号置为发送状态,Reset方法将信号置为不发送状态,WaitOne等待信号的发送。可以通过构造函数的参数值来决定其初始状态,若为true则非阻塞状态,为false为阻塞状态。如果某个线程调用WaitOne方法,则当信号处于发送状态时,该线程会得到信号, 继续向下执行。其区别就在调用后,AutoResetEvent.WaitOne()每次只允许一个线程进入,当某个线程得到信号后,AutoResetEvent会自动又将信号置为不发送状态,则其他调用WaitOne的线程只有继续等待.也就是说,AutoResetEvent一次只唤醒一个线程;而ManualResetEvent则可以唤醒多个线程,因为当某个线程调用了ManualResetEvent.Set()方法后,其他调用WaitOne的线程获得信号得以继续执行,而ManualResetEvent不会自动将信号置为不发送。也就是说,除非手工调用了ManualResetEvent.Reset()方法,则ManualResetEvent将一直保持有信号状态,ManualResetEvent也就可以同时唤醒多个线程继续执行。

//本质上AutoResetEvent.Set()方法相当于ManualResetEvent.Set()+ManualResetEvent.Reset();

//因此AutoResetEvent一次只能唤醒一个线程,其他线程还是堵塞
private static AutoResetEvent _workerEvent = new AutoResetEvent(false);
private static AutoResetEvent _mainEvent = new AutoResetEvent(false);

static void Process(int seconds)

{
Console.WriteLine("②子线程开始长时间运行的工作...");
Thread.Sleep(TimeSpan.FromSeconds(seconds));
Console.WriteLine("③子线程工作完成!");
_workerEvent.Set();

//--------------------------------------------------------

Console.WriteLine("④等待主线程完成其工作");

_mainEvent.WaitOne();

//--------------------------------------------------------

Console.WriteLine("⑧子线程开始第二个操作...");

Thread.Sleep(TimeSpan.FromSeconds(seconds));
Console.WriteLine("⑨子线程第二个操作工作完成!");
//这里是设置为有信号
_workerEvent.Set();
}

//简单来说只有调用Set()方法后才能执行WaitOne()后面的代码,AutoResetEvent和ManualResetEvent分别都有Set()改变为有信号 ,Reset()改变为无信号,WaitOne()将会阻塞当前调用的线程,直到有信号为止,即执行了Set()方法,WaitOne()方法还可以带指定时间的参数。
public static void RunTest()
{
//开启一个处理线程(子线程)
var t = new Thread((() => Process(10)));
t.Start();
Console.WriteLine("①等待一个子线程完成工作");
_workerEvent.WaitOne();
//--------------------------------------------------------

Console.WriteLine("⑤子线程第一个操作完成!");

Console.WriteLine("⑥在主线程上执行操作");
Thread.Sleep(TimeSpan.FromSeconds(5));
//主线程设置为有信号,即通知正在等待的线程有事件发生
_mainEvent.Set();
Console.WriteLine("⑦现在在子线程上运行第二个操作");

//--------------------------------------------------------

//执行到这个地方时,会等待set调用后改变了信号才接着执行

_workerEvent.WaitOne();
Console.WriteLine("⑩子线程第二个操作完成!");
//--------------------------------------------------------
Console.ReadKey();
}
}
---------------------

 

 

作者:风灵使
来源:CSDN
原文:https://blog.csdn.net/wulex/article/details/53932598
版权声明:本文为博主原创文章,转载请附上博文链接!

---------------------

转载于:https://www.cnblogs.com/asdyzh/p/9945349.html

你可能感兴趣的文章
Windbg调试Sql Server 进程
查看>>
linux调度器系列
查看>>
mysqladmin
查看>>
解决 No Entity Framework provider found for the ADO.NET provider
查看>>
SVN服务器搭建和使用(三)(转载)
查看>>
Android 自定义View (三) 圆环交替 等待效果
查看>>
设置虚拟机虚拟机中fedora上网配置-bridge连接方式(图解)
查看>>
HEVC播放器出炉,迅雷看看支持H.265
查看>>
[置顶] Android仿人人客户端(v5.7.1)——人人授权访问界面
查看>>
Eclipse 调试的时候Tomcat报错启动不了
查看>>
【安卓5】高级控件——拖动条SeekBar
查看>>
ES6内置方法find 和 filter的区别在哪
查看>>
Android入门之文件系统操作(二)文件操作相关指令
查看>>
Android实现 ScrollView + ListView无滚动条滚动
查看>>
Swift 中的指针使用
查看>>
Swift - 使用闭包筛选过滤数据元素
查看>>
alue of type java.lang.String cannot be converted to JSONObject
查看>>
搜索引擎选择: Elasticsearch与Solr
查看>>
JAVA设计模式之简单工厂模式与工厂方法模式
查看>>
③面向对象程序设计——封装
查看>>