控制threadpool執行緒的順序啟動 - WaitHandle.WaitAll 方法

本文主要是介绍控制threadpool執行緒的順序啟動 - WaitHandle.WaitAll 方法,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

[C#.NET][Thread] 執行緒的順序啟動 - WaitHandle.WaitAll 方法

WaitHandle.WaitAll 跟Thread.Join很像,都是執行緒等待,在功能上就是執行緒的順序啟動,如同我之前寫過的 [Thread] 執行緒的順序啟動 - Thread.Join方法,實作過程很簡單只需要注意以下兩點

1.WaitHandle是一個抽像類別所以我們得實體化它的子類別,也就是 ManualResetEvent 類別 或AutoResetEvent 類別,如下所示

static WaitHandle[] waitHandles = new WaitHandle[]     
{        new AutoResetEvent(false),        new AutoResetEvent(false)    
};

 

2.再來,看一下多載清單,WaitHandle.WaitAll方法只收WaitHandle[]參數

image

 


接下來則演練如何實作WaitHandle,我用一個類別將我要的資訊擺進去

 

public class Calculator
{public string Name { get; set; }public long Result { get; set; }private AutoResetEvent _WaitHandle;public AutoResetEvent WaitHandle{get { return _WaitHandle; }set { _WaitHandle = value; }}
}

用戶端的呼叫

 

static WaitHandle[] waitHandles = null;
static object _lock = new object();static void Main(string[] args)
{DateTime dt = DateTime.Now;Console.WriteLine("進入主執行緒");//建立集合List<Calculator> calculator = new List<Calculator>() {new Calculator{Result=0,WaitHandle=new AutoResetEvent(false),Name="NO.1"},new Calculator{Result=0,WaitHandle=new AutoResetEvent(false),Name="NO.2"}};//建立WaitHandle陣列,因為WaitHandle.WaitAll只收陣列waitHandles = new WaitHandle[calculator.Count];for (int i = 0; i < calculator.Count; i++){waitHandles[i] = calculator[i].WaitHandle;}ThreadPool.QueueUserWorkItem(new WaitCallback(DoTask), calculator[0]);ThreadPool.QueueUserWorkItem(new WaitCallback(DoTask), calculator[1]);//等待這兩隻執行緒完成工作WaitHandle.WaitAll(waitHandles);Console.WriteLine("子執行緒完成,花費時間 ={0})", (DateTime.Now - dt).TotalMilliseconds);Console.ReadKey();
}

模擬大量運算工作

static void DoTask(Object state)
{lock (_lock){if (_isTimeOut)return;Calculator calculator = (Calculator)state;Console.WriteLine("{0} 進入子執行緒", calculator.Name);AutoResetEvent reset = calculator.WaitHandle;for (long i = 0; i < 1000000000; i++){calculator.Result++;}Console.WriteLine("{0} 計算結果 :{1}", calculator.Name, calculator.Result.ToString());Console.WriteLine("{0} 離開子執行緒", calculator.Name);reset.Set();}
} 

執行結果就跟我想的一樣,因為 WaitHandle.WaitAll(waitHandles)的關係,主執行緒乖乖的等待所有執行緒完成工作, 

image


WaitHandle.WaitAll還可以設定等待時間,我們把WaitHandle.WaitAll(waitHandles)改成WaitHandle.WaitAll(waitHandles,2000),表示主執行緒願意等子執行緒2秒。

因為ThreadPool沒有Abort方法所以,我加一個變數_isTimeOut旗標,用來判斷執行緒是否結束工作。

再改裝一下程式碼,

 

static bool _isTimeOut=false; static void Main(string[] args) { …略 //等待這兩隻執行緒完成工作 WaitHandle.WaitAll(waitHandles,2000); _isTimeOut = true; Console.WriteLine("子執行緒完成,花費時間 ={0})", (DateTime.Now - dt).TotalMilliseconds); Console.ReadKey(); } 

static void DoTask(Object state) { lock (_lock) { if (_isTimeOut) return; …略 for (longi = 0; i < 1000000000; i++) { //離開子執行緒旗標 if (_isTimeOut) { Console.WriteLine("{0} 計算結果 :{1}", calculator.Name, calculator.Result.ToString()); Console.WriteLine("{0} 離開子執行緒", calculator.Name); return; } calculator.Result++; } …略 } }

 

執行結果,主執行緒等了2秒後,就不想等了,於是就叫子執行緒停下他的工作。

image


WaitHandle.WaitAny方法就是等待任何一隻執行緒完成工作

static void Main(string[] args)
{…略//等待任一隻執行緒完成工作int index = WaitHandle.WaitAny(waitHandles);_isTimeOut = true;Console.WriteLine("子執行緒完成,花費時間 ={0})", (DateTime.Now - dt).TotalMilliseconds);Console.ReadKey();
}

 

執行結果:可以觀察出當任一執行緒完成工作後則離開所有子執行緒

image

这篇关于控制threadpool執行緒的順序啟動 - WaitHandle.WaitAll 方法的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



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

相关文章

Python中提取文件名扩展名的多种方法实现

《Python中提取文件名扩展名的多种方法实现》在Python编程中,经常会遇到需要从文件名中提取扩展名的场景,Python提供了多种方法来实现这一功能,不同方法适用于不同的场景和需求,包括os.pa... 目录技术背景实现步骤方法一:使用os.path.splitext方法二:使用pathlib模块方法三

Python打印对象所有属性和值的方法小结

《Python打印对象所有属性和值的方法小结》在Python开发过程中,调试代码时经常需要查看对象的当前状态,也就是对象的所有属性和对应的值,然而,Python并没有像PHP的print_r那样直接提... 目录python中打印对象所有属性和值的方法实现步骤1. 使用vars()和pprint()2. 使

CSS实现元素撑满剩余空间的五种方法

《CSS实现元素撑满剩余空间的五种方法》在日常开发中,我们经常需要让某个元素占据容器的剩余空间,本文将介绍5种不同的方法来实现这个需求,并分析各种方法的优缺点,感兴趣的朋友一起看看吧... css实现元素撑满剩余空间的5种方法 在日常开发中,我们经常需要让某个元素占据容器的剩余空间。这是一个常见的布局需求

Python常用命令提示符使用方法详解

《Python常用命令提示符使用方法详解》在学习python的过程中,我们需要用到命令提示符(CMD)进行环境的配置,:本文主要介绍Python常用命令提示符使用方法的相关资料,文中通过代码介绍的... 目录一、python环境基础命令【Windows】1、检查Python是否安装2、 查看Python的安

Maven 配置中的 <mirror>绕过 HTTP 阻断机制的方法

《Maven配置中的<mirror>绕过HTTP阻断机制的方法》:本文主要介绍Maven配置中的<mirror>绕过HTTP阻断机制的方法,本文给大家分享问题原因及解决方案,感兴趣的朋友一... 目录一、问题场景:升级 Maven 后构建失败二、解决方案:通过 <mirror> 配置覆盖默认行为1. 配置示

SpringBoot排查和解决JSON解析错误(400 Bad Request)的方法

《SpringBoot排查和解决JSON解析错误(400BadRequest)的方法》在开发SpringBootRESTfulAPI时,客户端与服务端的数据交互通常使用JSON格式,然而,JSON... 目录问题背景1. 问题描述2. 错误分析解决方案1. 手动重新输入jsON2. 使用工具清理JSON3.

使用jenv工具管理多个JDK版本的方法步骤

《使用jenv工具管理多个JDK版本的方法步骤》jenv是一个开源的Java环境管理工具,旨在帮助开发者在同一台机器上轻松管理和切换多个Java版本,:本文主要介绍使用jenv工具管理多个JD... 目录一、jenv到底是干啥的?二、jenv的核心功能(一)管理多个Java版本(二)支持插件扩展(三)环境隔

Java中Map.Entry()含义及方法使用代码

《Java中Map.Entry()含义及方法使用代码》:本文主要介绍Java中Map.Entry()含义及方法使用的相关资料,Map.Entry是Java中Map的静态内部接口,用于表示键值对,其... 目录前言 Map.Entry作用核心方法常见使用场景1. 遍历 Map 的所有键值对2. 直接修改 Ma

Mybatis Plus Join使用方法示例详解

《MybatisPlusJoin使用方法示例详解》:本文主要介绍MybatisPlusJoin使用方法示例详解,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,... 目录1、pom文件2、yaml配置文件3、分页插件4、示例代码:5、测试代码6、和PageHelper结合6

Java中实现线程的创建和启动的方法

《Java中实现线程的创建和启动的方法》在Java中,实现线程的创建和启动是两个不同但紧密相关的概念,理解为什么要启动线程(调用start()方法)而非直接调用run()方法,是掌握多线程编程的关键,... 目录1. 线程的生命周期2. start() vs run() 的本质区别3. 为什么必须通过 st