C#多线程之线程通讯(AutoResetEvent)
作者:農碼一生 发布时间:2021-12-26 01:48:55
一、简介
我们在线程编程的时候往往会涉及到线程的通信,通过信号的接受来进行线程是否阻塞的操作。
AutoResetEvent 允许线程通过发信号互相通信。通常,此通信涉及线程需要独占访问的资源。具体方法和扩展方法请详见AutoResetEvent类,最常用方法中就有Set()和WaitOne()。
线程通过调用 AutoResetEvent 上的 WaitOne 来等待信号。如果 AutoResetEvent 处于非终止状态,则该线程阻塞,并等待当前控制资源的线程通过调用 Set 发出资源可用的信号。AutoResetEvent 的非终止状态可以通过构造函数在设置。
通俗的来讲只有等myResetEven.Set()成功运行后,myResetEven.WaitOne()才能够获得运行机会;Set是发信号,WaitOne是等待信号,只有发了信号,
等待的才会执行。如果不发的话,WaitOne后面的程序就永远不会执行。
AutoResetEvent myEvent = new AutoResetEvent(false);
这里构造函数中的参数false就代表该状态为非终止状态,相反若为true则为终止状态。
二、代码
案例一:
public class Program
{
const int cycleNum = 10;static void Main(string[] args)
{
// 参数:
// workerThreads:
// 要由线程池根据需要创建的新的最小工作程序线程数。
// completionPortThreads:
// 要由线程池根据需要创建的新的最小空闲异步 I/O 线程数。
// 返回结果:如果更改成功,则为 true;否则为 false。
//public static bool SetMinThreads(int workerThreads, int completionPortThreads);
ThreadPool.SetMinThreads(1, 1);
// 参数:
// workerThreads:
// 线程池中辅助线程的最大数目。
// completionPortThreads:
// 线程池中异步 I/O 线程的最大数目。
// 返回结果:如果更改成功,则为 true;否则为 false。
//public static bool SetMaxThreads(int workerThreads, int completionPortThreads);
ThreadPool.SetMaxThreads(5, 5);
for (int i = 1; i <= cycleNum; i++)
{
ThreadPool.QueueUserWorkItem(new WaitCallback(testFun), i.ToString());
}
Console.WriteLine("主線程執行!");
Console.WriteLine("主線程終止!");
Console.WriteLine("線程池終止!");
Console.ReadKey();
}
public static void testFun(object obj)
{
Console.WriteLine(string.Format("{0}:第{1}個線程", DateTime.Now.ToString(), obj.ToString()));
Thread.Sleep(5000);
}
}
运行结果:
这里可以看出,线程池里线程的执行不影响主线程的运行,线程池虽然可以管理多线程的执行,但是却无法知道它什么时候终止。
案例二:
public class Program
{
const int cycleNum = 10;
static int cnt = 10;
static AutoResetEvent myEvent = new AutoResetEvent(false);
static void Main(string[] args)
{
// 参数:
// workerThreads:
// 要由线程池根据需要创建的新的最小工作程序线程数。
// completionPortThreads:
// 要由线程池根据需要创建的新的最小空闲异步 I/O 线程数。
// 返回结果:如果更改成功,则为 true;否则为 false。
//public static bool SetMinThreads(int workerThreads, int completionPortThreads);
ThreadPool.SetMinThreads(1, 1);
// 参数:
// workerThreads:
// 线程池中辅助线程的最大数目。
// completionPortThreads:
// 线程池中异步 I/O 线程的最大数目。
// 返回结果:如果更改成功,则为 true;否则为 false。
//public static bool SetMaxThreads(int workerThreads, int completionPortThreads);
ThreadPool.SetMaxThreads(5, 5);
for (int i = 1; i <= cycleNum; i++)
{
ThreadPool.QueueUserWorkItem(new WaitCallback(testFun), i.ToString());
}
Console.WriteLine("主線程執行!");
Console.WriteLine("主線程終止!");
myEvent.WaitOne();
Console.WriteLine("線程池終止!");
Console.ReadKey();
}
public static void testFun(object obj)
{
cnt -= 1;//信號量自減
Console.WriteLine(string.Format("{0}:第{1}個線程", DateTime.Now.ToString(), obj.ToString()));
Thread.Sleep(5000);
if (cnt == 0)
{
myEvent.Set();
}
}
}
运行结果:
上面例子中一开始非终止状态,当遇到WaitOne()方法时则会阻塞线程,在没有set()时将一直处于阻塞状态.
三、总结
既然说到了AutoResetEvent,就不得不说ManualResetEvent,这两个方法几乎相同,不同的地方就在于AutoResetEvent的WaitOne()方法执行后会自动又将信号置为不发送状态也就是阻塞状态,当再次遇到WaitOne()方法是又会被阻塞,而ManualResetEvent则不会,只要线程处于非阻塞状态则无论遇到多少次WaitOne()方法都不会被阻塞,除非调用ReSet()方法来手动阻塞线程。
来源:https://www.cnblogs.com/wml-it/p/14823469.html
猜你喜欢
- java中的LIST在删除时,一般会用list.remove(o); 但这样往往会出现问题,先来看下面的这段代码:package com.d
- 前言说起整合自然离不开ssm,我本身并不太喜欢ORM,尤其是MyBatis,把SQL语句写在xml里,尤其是大SQL,可读性不高,出错也不容
- 前言:在日常开发中经常会遇到字符串匹配问题,我们就来学习使用Java中的一些方便快捷的方法来解决这个问题吧使用String类Java自带的字
- 本文实例讲述了C#编程之事务用法。分享给大家供大家参考,具体如下:ado.net2.0的SqlTransaction使用方法/////ado
- instanceof判断某个对象是否是某个类的实例或者某个类的子类的实例。它的判断方式大概是这样的:public<T> bool
- 1.抽象类与抽象方法:(1)使用关键字abstract修饰的类,称为抽象类.(2)抽象类只是用到一个类所具有的行为,不能单独通过创建对象来使
- 场景在任何一个Form表单的操作页面或者数据台账的查询页面,基本都会看到一个清除的按钮,其功能就是用来清除我们需要抛弃的已经写入到控件内的数
- springboot http转https一、安全证书的生成可以使用jdk自带的证书生成工具,jdk自带一个叫keytool的证书管理工具,
- java的接口解耦方式我只想把抽象的东西说的具体,或者说,听起来简单些,明白些。。。学过java的人都知道,java是单继承的,也就是说一个
- 1. 理解abstract:抽象的2. 作用abstract可以用来修饰类、方法。不能用abstract修饰变量、代码块、构造器。不能用ab
- 本文以实例形式分析了C#中Predicate<T>与Func<T, bool>泛型委托的用法,分享给大家供大家参考之
- 我们都知道在一些特殊的场景,我们需采用特殊的编码格式,如:UTF-8,但是系统默认的编码为ISO-8859-1那么我们就需要将编码转换为我们
- Android 中RecycleView实现item的点击事件RecycleView现在已经越来越受到大家的重视,因为他既可以代替listV
- Spring中提供了很多PostProcessor供开发者进行拓展,例如:BeanPostProcessor、BeanFactoryPost
- 一、安装MongoDB4.0.3(××)1.1、官方安装文档https://docs.mongodb.com/manual/tutorial
- 本文实例为大家分享了C#二维码图片识别的具体代码,供大家参考,具体内容如下怎么用NuGet和怎么配置log4net就不介绍了,直接上代码(V
- @ApiModel使用场景在实体类上边使用,标记类时swagger的解析类概述提供有关swagger模型的其它信息,类将在操作中用作类型时自
- springboot sqlSessionFactoryBean自定义1.新建一个配置类,加上configuration注解2.定制化Sql
- 前言本文主要给大家介绍的是关于Java通过Class类获取Class对象的相关内容,分享出来供大家参考学习,下面话不多说了,来一起看看详细的
- 本文实例讲述了C#操作windows系统进程的方法。分享给大家供大家参考。具体如下:这段代码演示了如何根据进程名关闭进程和启动进程/// &