基于C#实现多线程启动停止暂停继续
大家好!我是付工。
大部分初学者在学习C#上位机编程时,多线程是一个很难逾越的鸿沟,不合理地使用多线程,会导致经常出现各种奇怪的问题,这也是很多初学者不敢使用多线程的原因。但是在实际开发中,多线程是一个不可避免的技术栈,基本上每个项目都会使用到,因此学好多线程技术,很重要。
一、多线程原理
首先,我们要了解什么是多线程,多线程是一种技术,能够让一个程序同时运行多个独立的执行流程,这个执行流程即线程,这样就可以提高程序的并发性和效率,使程序能够更有效地利用系统资源。
打个比方,刚创业的时候,我们可能是一个人身兼多职,既要对接业务,又要做技术,还需要管理财务,虽然你可以同时做这些事情,但毕竟只有一个人,这里的同时,其实是靠“时间管理”来实现的,这就是单核CPU实现多线程的原理,依靠时间片切换来实现多个任务,这个时间片很短,通常在10-100ms数量级,因此,让我们感觉是同时进行的。
随着技术的不断发展,现在的计算机CPU基本上都是多核的。8核、16核,都很常见,多核意味着有多个核心,可以同时运行多个任务。
因此,多核CPU上的多线程才是真正的多线程,它能让你的多段逻辑同时工作,多线程,可以真正发挥出多核CPU的优势来,达到充分利用CPU的目的。
如果你做项目不使用多线程,不仅是技术的问题,也是对电脑资源的极大浪费,就像买了一辆性能车,但是只用来日常代步。
二、多线程发展
我们知道了多线程技术可以保证我们代码的高效运行,提高CPU资源的使用率,为什么很多人不敢使用,主要是因为多线程如果使用不当,容易出现各种奇怪的问题。
我们必须要明确一点,多线程是“不可控的”,不要把多线程当做一个开关,需要的时候就开一下,不需要的时候就关闭一下。从微观角度来看,多线程是靠CPU调度来实现的,我们常说的开启多线程,只是告诉CPU,这个线程可以开了,但是至于是立即开,还是等一会再开,这个是由CPU调度决定的,对于关闭多线程也是一样。
我们后续提到的控制多线程启动、停止、暂停、继续,这些都是.NET框架中提供的一些接口(方法)给开发人员,这样程序员就可以间接地实现多线程。
微软的多线程技术也是在一直发展中,在.NET 1.0中就出现了多线程Thread,到2.0时推出了ThreadPool线程池,再到3.0是出现了Task,Task也是我们目前使用比较多的,Task被称之为多线程的最佳实践,再到4.0时推出Parallel并行编程,再到4.5推出async/await语法糖,它让我们可以用同步方法来实现异步编程。
三、多线程启停
Task是我们使用多线程开发中经常使用的一个类,这个类中提供了丰富的API函数,让我们可以很方便地对多线程进行管理,包括开启多线程了,就有很多种方法,比如Task.Run、Task.Factory.StartNew、Start等,由于篇幅有限,这里以其中一种进行说明。
我们来使用多线程实现一个简单的案例,我们来做一个线程任务,这个任务很简单,就是让一个值类型的变量,每间隔100ms,自增一次,到一个值后,再0开始重新计数,然后将这个值显示在界面上,界面如下所示:
所以该任务执行代码如下:
我们可以看到在方法里调用了一个cts对象,这个对象就是CancellationTokenSource的对象,因此我们需要创建一个CancellationTokenSource对象cts,同时在属性CurrentValue中,要显示控件的值,这里需要用到委托实现跨线程访问的问题,这个我们后续专题讲解,代码如下:
然后在启动线程按钮的事件里,编写代码如下:
停止线程按钮的事件里,只需要调用cts的Cancel方法即可:
我们可以看到,这里就是通过cts来控制cts的IsCancellationRequested属性,进而实现多线程的控制,这里的cts.IsCancellationRequested类似于一个布尔类型的标志位,但是CancellationTokenSource的作用不仅如此,还可以在此基础上实现多线程超时判断,注册事件等更复杂的多线程操作。
四、多线程暂停继续
多线程的暂停继续,.NET为我们提供了另外一个对象——ManualResetEvent,这个对象会有一个值,这个值是布尔类型,就像一个门闸一样,True是打开门闸,False是关闭门闸,所以想要暂停多线程就调用这个对象的Reset方法,想要继续多线程就调用这个对象的Set方法,使用非常简单。
首先我们创建一下这个对象,可以通过构造方法,给这个对象赋初始值,我这里为True,这样就能直接运行,不会阻塞,代码如下:
但是如果希望这个对象与多线程有所联系,必须要在多线程的方法里体现这个对象的作用,这个是调用这个对象的WaitOne方法,表示在调用的地方阻塞住,通过判断True或者False来决定是否继续执行,就像大家开车过高速收费站一样,即使现在普遍采用ETC了,在入口也需要减速,有一个ETC识别的过程,识别成功才会抬杆,识别不对,杆子是不会自动抬起的,这个是一样的道理。
所以线程执行代码修改如下:
对比一下,其实就是加了一个manual.WaitOne()。
线程暂停继续代码如下:
暂停继续的使用除了ManualResetEvent,还有一个AutoResetEvent,AutoResetEvent和ManualResetEvent的用法基本上是一样的,这里就不过多赘述,大家可以自己尝试一下。
这两者的区别在于一个是手动,一个是自动,AutoResetEvent会在置位之后自动复位,这样体现在多线程里,就是会只执行一次,就像大家进小区一样,如果有10辆车在排队,这时候如果自动模式,每次都要抬杆落杆,每次只允许进一辆车,如果是手动模式,可以由保安控制门闸打开,等10辆车都进去之后,再由保安将门闸关闭。
基于C#实现多线程启动停止暂停继续的更多相关文章
- Quartz的任务的临时启动和暂停和恢复
Quartz的任务的临时启动和暂停和恢复 在项目中需要手动启停某些服务,那么需要有一个控制这些任务的类.由于任务是有Quartz控制的,我们只需要通过Quartz的相关的API实现相关的功能即可. p ...
- Linux Systemd——在RHEL/CentOS 7中启动/停止/重启服务
RHEL/CentOS 7.0中一个最主要的改变,就是切换到了systemd.它用于替代红帽企业版Linux前任版本中的SysV和Upstart,对系统和服务进行管理.systemd兼容SysV和Li ...
- 在CentOS 7中启动/停止/重启服务
RHEL/CentOS 7.0中一个最主要的改变,就是切换到了systemd.它用于替代红帽企业版Linux前任版本中的SysV和Upstart,对系统和服务进行管理.systemd兼容SysV和Li ...
- 控制Linux下 mono 服务的启动停止
当Window下的服务部署到Linux的时候,我们一般用Mono.service 来启动停止.参数比较多,不太好用.于是有个这个Shell脚本. 用法:moa s1 start #启动 ...
- Linux Oracle服务启动&停止脚本与开机自启动
在CentOS 6.3下安装完Oracle 10g R2,重开机之后,你会发现Oracle没有自行启动,这是正常的,因为在Linux下安装Oracle的确不会自行启动,必须要自行设定相关参数,首先先介 ...
- Python多线程启动http.server
OS: Windows 8.1 with update 关键字:Python3.4, http.server, Thread 例子代码如下: import os from threading impo ...
- 批处理命令行CMD启动停止重启IIS的命令
原文:批处理命令行CMD启动停止重启IIS的命令 启动IIS: net start iisadmin (IIS的整个服务) net start w3svc (WWW网页WEB服务) ...
- selenium之多线程启动grid分布式测试框架封装(四)
九.工具类,启动所有远程服务的浏览器 在utils包中创建java类:LaunchAllRemoteBrowsers package com.lingfeng.utils; import java.n ...
- bat启动/停止oracle服务
原文:bat启动/停止oracle服务 自己的电脑比较慢,尤其装了oracle10g后,服务开启和关闭用bat文件操作省事点 开启服务 @echo offnet start OracleService ...
- 绿色版Tomcat 启动 + 停止 + 随系统自动启动 - - 博客频道 - CSDN.NET
body { font-family: "Microsoft YaHei UI","Microsoft YaHei",SimSun,"Segoe UI ...
随机推荐
- cornerstone中raft_server_req_handlers源码解析
1.概述 之前说过raft_server是cornerstone的核心,其中充满了很多req的发送,那么follower收到leader的req会怎么处理呢? 本文就是来解析cornerstone中处 ...
- apisix问题记录
负载均衡 可以给 rest api(9080)做负载均衡 不可以给dashboard做负载均衡,否则会出现闪退,dashboard之间的token并不是通用的 路由导出 openapi 路由导出ope ...
- zynq 按照传统的Linux开发模式制作系统
参考资料 xilinx wiki: https://xilinx-wiki.atlassian.net/wiki/spaces/A/pages/460653138/Xilinx+Open+Source ...
- python常用模块汇总
os模块 os.remove() 删除文件 os.unlink() 删除文件 os.rename() 重命名文件 os.listdir() 列出指定目录下所有文件 os.chdir() 改变当前工作目 ...
- 生成式AI如何辅助医药行业智能营销
生成式AI如何辅助医药行业智能营销 生成式AI在医药行业的智能营销中发挥着日益重要的作用,它通过多种方式辅助医药企业提升市场洞察能力.优化营销策略.增强客户互动和体验,从而推动销售增长和品牌价值的提升 ...
- 指针, C语言的精髓
指针, C语言的精髓 莫队先咕几天, 容我先讲完树剖 (因为后面树上的东西好多都要用树剖求 LCA). 什么是指针 保存变量地址的变量叫做指针. 这是大概的定义, 但是Defad认为这个定义不太好理解 ...
- 揭秘“山姆黄牛”背后的技术逻辑:用Java实现会员管理系统的防黄牛策略
在浙江绍兴的山姆超市外,"黄牛"现象引发了广泛关注.这些"黄牛"通过提供带入和结账服务,让未办理会员卡的消费者也能进入超市购物.这一行为不仅扰乱了市场秩序,也对 ...
- 【Amadeus原创】域用户完美执行应用程序
企业环境中,为了安全起见一般都没有赋予域用户或者企业的PC客户端用户管理员权限. 但偶尔会有个别的程序一定需要管理员身份才能执行,如财务某些程序或专业的应用程序.那么如何不赋予用户管理员权限及密码但又 ...
- 注册美区 Apple ID 账号!都2020年了,你还没有一个自己的海外苹果ID?
写在前面: 小伙伴们学腻了技术,不防今天来点大家都感兴趣的海外苹果 Apple ID 吧! 今天就教大家怎么注册美区 Apple ID,这个方法也是目前注册苹果美区 Apple ID 最快最简单的 ...
- GooseFS 统一命名空间 | 加速存储业务访问
01 前言 GooseFS是 腾讯云存储团队推出的分布式缓存方案,主要针对需要缓存加速的数据湖业务场景,提供基于对象存储COS服务的近计算端数据加速层. 统一命名空间是GooseFS提供的透明命名 ...