线程 ManualResetEvent 类
Reset(): 当一个线程开始一个活动(此活动必须完成后,其他线程才能开始)时, 它调用 Reset 以将 ManualResetEvent 置于非终止状态。此线程可被视为控制 ManualResetEvent。
为了把状态修改为无信号的,必须调用ReSet()方法。
WaitOne(): 调用ManualResetEvent 上的 WaitOne 的线程将阻止,并等待信号。
Set ()当控制线程完成活动时,它调用 Set 以发出等待线程可以继续进行的信号。并释放所有等待线程。Set将事件状态设置为终止状态,允许一个或多个等待线程继续。
为了把状态修改为有信号的,必须调用Set()方法。
ManualResetEvent对象只能拥有两种状态之一:有信号(True)或无信号(false)。ManualResetEvent类继承于WaitHandle类,其构造函数的参数可确定对象的初始状态。
Set()和Reset()方法返回一个布尔值,表示是否进行了成功的修改。
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
namespace ManualResetshiyan
{
class Program
{
static void Main(string[] args)
{
ManualResetEvent mansig;
mansig = new ManualResetEvent(false);
Console.WriteLine("ManualResetEvent Before WaitOne");
bool b = mansig.WaitOne(1000, true);
Console.WriteLine("ManualResetEvent After WaitOne" + b);
Console.ReadLine();
}
}
}上面的例子中,构造了false值的ManualResetEvent对象,布尔值False把ManualResetEvent对象的初始状态设置为无信号。接着调用基类WaigHandle的WaitOne()方法。程序块在WaitOne()方法中暂停一秒,然后因为超时而退出。ManualResetEvent的状态仍然是False,因而WaitOne()返回的布尔值b是False。
下面的例子把有信号改为无信号,调用ReSet()方法,Set()方法。
- using System;
- using System.Collections.Generic;
- using System.Text;
- using System.Threading;
- namespace 同步
- {
- class Program
- {
- static void Main(string[] args)
- {
- ManualResetEvent mansig;
- mansig = new ManualResetEvent(true);
- bool state = mansig.WaitOne(9000, true);
- Console.WriteLine("ManualResetEvent After WaitOne" + state);
- mansig.Reset();
- state = mansig.WaitOne(9000, true);
- Console.WriteLine("ManualResetEvent After WaitOne" + state);
- mansig.Set();
- state = mansig.WaitOne(9000, true);
- Console.WriteLine("ManualResetEvent After WaitOne" + state);
- }
- }
- }
在ManualReset中,MnualTResetEvent对象的构造函数将其状态设置为有信号(true),结果,线程不在第一个
WaitOne()方法中等待,并返回True值。接着,ManualResetEvent对象的状态重新设置为无信号的(false),于是线程在超时之前必须等待5秒,调用Set()方法后也不用等待。
下面在看一个程序:
- using System;
- using System.Collections.Generic;
- using System.Text;
- using System.Threading;
- namespace 同步实验
- {
- class Program
- { ///
- /// ManualResetEvent建立时是把false作为start的初始状态,这个类用于通知另一个线程,让它等待一个或多个线程。
- /// 如这个例子中,等待线程thread1线程调用mre.WaitOne(), 用于发信号的线程调用mre.Set().
- ///
- public static ManualResetEvent mre = new ManualResetEvent(false);
- public static void trmain()
- {
- Thread tr = Thread.CurrentThread;
- Console.WriteLine(tr.Name + " 开始第一波等待");
- mre.WaitOne(); //等到什么时候呢?等到mre.Set()被调用
- Console.WriteLine(tr.Name + " 第一波启动t");
- mre.Reset(); //再次重置
- Console.WriteLine(tr.Name + " 开始第二波等待");
- mre.WaitOne(); //再次等待
- Console.WriteLine(tr.Name + " 第二波启动");
- for (int x = 0; x < 10; x++)
- {
- Thread.Sleep(1000);
- Console.WriteLine(tr.Name + ": " + x);
- }
- }
- static void Main(string[] args)
- {
- Thread thrd1 = new Thread(new ThreadStart(trmain));
- thrd1.Name = "thread1";
- thrd1.Start();
- Thread thrd2 = new Thread(new ThreadStart(trmain));
- thrd2.Name = "thread2";
- thrd2.Start();
- for (int x = 0; x < 10; x++)
- {
- Thread.Sleep(900);
- Console.WriteLine("Main :" + x);
- if (5 == x)
- {
- mre.Set(); //子线程的mre.WaitOne()可以执行了。第一次等待进程
- //; //如果什么都不做呢,mre.Wait()那个线程就一直等在那里了?
- }
- }
- while (thrd1.IsAlive)
- {
- Thread.Sleep(1000);
- Console.WriteLine("Main: waiting for thread to stop...");
- mre.Set(); //第二次通知等待进程
- }
- }
- }
- }
下面在看一个关于ManualResetEvent waitany的程序:
waitany一直等到有信号 才开始执行下面的语句.
- using System;
- using System.Collections.Generic;
- using System.Text;
- using System.Threading;
- namespace 同步实验
- {
- class Program
- {
- public static ManualResetEvent m_eventTemporaryTrigger;
- public static ManualResetEvent m_eventQuitTemporary;
- private static string m_triggerParam;
- public static void TemporaryConnThreadTrigger(String param)
- {
- m_triggerParam = param;
- m_eventTemporaryTrigger.Set();
- }
- static void Main(string[] args)
- {
- m_eventTemporaryTrigger =new ManualResetEvent(true);
- m_eventQuitTemporary = new ManualResetEvent(true);
- //m_eventQuitTemporary = new ManualResetEvent(false);
- m_eventTemporaryTrigger.Reset(); //临时线程处于工作之中时,m_eventTemporaryTrigger始终处于被触发状态
- // Trigger.strmain();
- WaitHandle[] events = new WaitHandle[2];
- events[0] = m_eventQuitTemporary;
- events[1] = m_eventTemporaryTrigger;
- //等待退出信号事件或触发事件
- // 返回结果:
- // 满足等待的对象的数组索引。
- int index = WaitHandle.WaitAny(events);
- Console.WriteLine("run no wait");
- if (index == 0)
- {//如果是将Main(),第三行置为false则不执行下面语句
- Console.WriteLine("m_eventQuitTemporary run");
- Console.WriteLine(m_triggerParam);
- }
- }
- }
- public class Trigger
- {
- public static void strmain()
- {
- Program.TemporaryConnThreadTrigger("m_eventQuitTemporary run show");
- }
- }
- }
要注意的是ManualResetEvent和AutoResetEvent 的构造函数都有一个bool的参数,用这个参数可以指定初始情况下,同步对象的处于阻塞(设置为false)还是非阻塞(设置为true)的状态。
另外WaitOne方法也可以带两个参数:
WaitOne (int millisecondsTimeout,bool exitContext)
millisecondsTimeout:等待的毫秒数,或为 Timeout.Infinite (-1),表示无限期等待。
exitContext:为 true,则等待之前先退出上下文的同步域(如果在同步上下文中),然后在稍后重新获取它;否则为false。
就是说,等待是可以加上一个期限的,如果等待的同步对象一直都不Set()的话,那么程序就会卡死,所以在WaitOne方法里面可以放置一个时间期限,单位是毫秒。
线程 ManualResetEvent 类的更多相关文章
- FreeOnTerminate 的线程在线程管理类的Destroy释放时手工释放的问题
这个问题折腾了我整整一天. 有一个线程管理类,集中管理所有新建的线程, 线程统一在创建时标识 FreeOnTerminate 为 True. 因为有的线程是不限次循环的,所以在管理类最后 Destro ...
- Qt 学习之路 :Qt 线程相关类
希望上一章有关事件循环的内容还没有把你绕晕.本章将重新回到有关线程的相关内容上面来.在前面的章节我们了解了有关QThread类的简单使用.不过,Qt 提供的有关线程的类可不那么简单,否则的话我们也没必 ...
- C#中假设正确使用线程Task类和Thread类
C#中使用线程Task类和Thread类小结 刚接触C#3个月左右.原先一直使用C++开发.由于公司的须要,所地採用C#开发.主要是控制设备的实时性操作,此为背景. 对于C#中的Task和Thread ...
- 工作线程基类TaskSvc
工作线程基类TaskSvc 前端时间用ACE写代码,发ACE_Task确实好用.不但能提供数量一定的线程,还能够让这些继承的线程函数自由访问子类的private和protected变量.此外,ACE_ ...
- Java多线程之线程其他类
Java多线程之线程其他类 实际编码中除了前面讲到的常用的类之外,还有几个其他类也有可能用得到,这里来统一整理一下: 1,Callable接口和Future接口 JDK1.5以后提供了上面这2个接口, ...
- 『TensorFlow』线程控制器类&变量作用域
线程控制器类 线程控制器原理: 监视tensorflow所有后台线程,有异常出现(主要是越界,资源循环完了)时,其should_stop方法就会返回True,而它的request_stop方法则用于要 ...
- linux通过c++实现线程池类
目录 线程池的实现 线程池已基于C++11重写 : 基于C++11实现线程池的工作原理 前言 线程池的概念 使用原因及适用场合 线程池的实现原理 程序测试 线程池的实现 线程池已基于C++11重写 : ...
- java并发编程:线程安全管理类--原子包--java.util.concurrent.atomic
java.util.concurrent.atomic 的描述 AtomicBoolean 可以用原子方式更新的 boolean 值. AtomicInteger 可以用原子方式更新的 int 值. ...
- JUC——ThreadFactory线程工厂类(四)
ThreadFactory线程工厂类 在默认情况下如果要想创建一个线程类对象,大部分情况的选择是:直接通过子类为父类进行实例化,利用Runnable子类为Runnable接口实例化. 或者直接调用La ...
随机推荐
- 最短路径算法 2.Dijkstra算法
Dijkstra 算法解决的是带权重的有向图上单源最短路径问题,该算法要求所有边的权重都为非负值.该算法的时间复杂度是O(N2),相比于处理无负权的图时,比Bellmad-Ford算法效率更高. 算法 ...
- 从0开始 java 网站开发(jsp)【1】
前提:安装java 并配置环境变量 java下载地址: http://www.java.com/zh_CN/ 环境变量配置 本地PC路径: 电脑--属性--高级--环境变量 在系统变量中: 新建 名: ...
- 【转】手把手教你:Ubuntu14+apache2+django1.7+python2.7下网页/网站部署
本人亲自尝试了网上众多的部署网页/网站方法,绝大多数都未能试验成功,这次的项目光部署这块遇到了很多问题,大概耗费了我一个星期. 本着:王道论坛中的赠人玫瑰,手留余香的精神.我把自己一路所走的历程发布出 ...
- git使用ssh密钥(转)
git使用https协议,每次pull, push都要输入密码,相当的烦.使用git协议,然后使用ssh密钥.这样可以省去每次都输密码. 大概需要三个步骤:一.本地生成密钥对:二.设置github上的 ...
- 【个人训练】(POJ3279)Fliptile
最近在刷kuangbin神犇的各种套题....感觉自己好弱啊.....还是要多多训练,跟上大神的脚步.最近的这十几题都比较水,记下来这一条我比较印象深刻.也比较难的题目吧(之后应该不会再有水题写了,珍 ...
- Freemarker 的 Shiro 标签使用详解
一.引入依赖(已解决版本冲突) <!-- shiro-freemarker-tags start --> <dependency> <groupId>net.min ...
- flask中static_folder与static_url_path的区别与联系
# -*- coding:utf-8 -*- from flask import Flask, url_for app1 = Flask(__name__, static_folder='mystat ...
- Mapper的方式总结
Mapper的方式总结: <mappers> <!-- 通过package元素将会把指定包下面的所有Mapper接口进行注册 --> <package name=&quo ...
- JSONP跨域jQuery处理整理(附天气数据实例)
写在前面 跨域的解决方案有多种,其中最常见的是使用同一服务器下的代理来获取远端数据,再通过ajax进行读取,而在这期间经过了两次请求过程,使得获取数据的效率大大降低,这篇文章蓝飞就为大家介绍一下解决跨 ...
- C++STL——队列
一.相关定义 原理:queue 队列也是一个线性存储表,元素数据的插入在表的一端进行,在另一端删除,从而构成了一个先进先出FIFO(First In First Out)表. 队头&队尾:插入 ...