首页 > 编程语言 >基于C#实现多线程启动停止暂停继续

基于C#实现多线程启动停止暂停继续

时间:2025-01-18 17:16:14浏览次数:1  
标签:Task cts C# 对象 线程 暂停 多线程 CPU

大家好!我是付工。

大部分初学者在学习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辆车都进去之后,再由保安将门闸关闭。

标签:Task,cts,C#,对象,线程,暂停,多线程,CPU
From: https://www.cnblogs.com/xbdedu/p/18678604

相关文章

  • [ARC 058 - E]Iroha and Haiku
    传送门解题步骤首先可以发现题目范围非常小,尤其是\(X,Y,Z\),所以考虑类似状压、数位dp、双向搜索等算法。官方题解中给的是数位dp,那我这里就讲讲状压了对于\(N\leq40\),很明显不能对其进行状压并且没意义,那么对于\(X,Y,Z\)呢?因为题目要求连续一段数满足要求,且\(X+Y+Z\leq17,......
  • [HarekazeCTF2019]baby_rop2(read的libc)
    一个normal的栈溢出,没有system和binsh,为ret2libc这里也没有常见的write和puts,所以我们用read泄露libc基址,并使用printf打印read的地址这里注意printf的第一个参数必须是格式字符串,即WelcometothePwnWorldagain(地址为0x0400770,第二个参数设为read_got(got表泄露)再找一下6......
  • [每日 C] No Prime Differences
    思路首先转化题意构造转化个蛋你发现\(n,m\)只要有一个不是质数,构造就是简单的考虑\(n,m\)都是质数的情况:你可以如下构造\[\begin{bmatrix}1&2&3&\cdots&m-1&m\\m+2&m+3&m+4&\cdots&m&m+1\\2m+3&2m+4&......
  • winform使用依赖注入框架Autofac的一些记录
    由于winform的framework框架无法实现core那样的依赖注入,必须借助于依赖注入框架来实现。此次使用Autofac,由于DAL被BLL引用,而BLL又被主程序引用,所以在framework里要实现依赖注入,主程序必须引用DAL和BLL,才可以在主程序里面对DAL和BLL进行注册,这又违背了解耦的原则,所以只能在BLL和主......
  • Invicti v25.1.0 for Windows - Web 应用程序安全测试
    Invictiv25.1.0forWindows-Web应用程序安全测试Invicti(formerlyNetsparker)|WebApplicationandAPISecurityforEnterprise请访问原文链接:https://sysin.org/blog/invicti/查看最新版。原创作品,转载请保留出处。作者主页:sysin.orgInvicti是一种自动化但完全......
  • THUWC2025题解
    Day1T1构造一个排列,使满足最多的形如\([l,r]\)内单调递增/减。一个简单的线段树优化DP,设状态\(f_{i,0/1}\)即可转移,\(O(n\logn)\)。T2支持往集合中加三维带权点,查询集合中没有任何一维与给出点对应维度相等的最大点权。唐题。一种暴力的想法是三维数点之类的,不太能......
  • [每日 C] MEX Game 1
    前言泻药,吉司机线段树学不动冷静的利用时间已经变成了不冷静的浪费时间,干脆打两道\(\rm{C}\)冷静一下思路看到\(\rm{MEX}\)了,无敌,看到\(2,1,0\)了,无敌但是应该不是这个方向先转化题意\(\textrm{Alice,Bob}\)轮流进行游戏,\(\textrm{Alice}\)每次取......
  • SpringCloudAlibaba:从0搭建一套快速开发框架-06 告别重复代码,使用Freemarker轻松生成
    序言:上篇主要优化完善公共模块,本篇主要创建一个生成代码的独立模块,提升开发效率,避免繁琐的重复的crud操作。由于内容较多,我就分两节写了。本节我们主要以创建项目并简单的生成数据库实体类即可,下节我们会直接搞完。Freemarker是什么Freemarker是一个基于Java的模板引擎......
  • P9730 [CEOI2023] Grading Server
    这是什么神仙题啊。本题主要思路:优化转移决策,减少dp状态。我们发现减一层盾其实就是给自己加攻击,所以我们将初始生命值(攻击力)\(C_H\)和\(C_G\)重新表示为\(A_1=C_H-f_GS\),\(A_2=C_G-f_HS\),让\(F_1=f_G\),\(F_2=f_H\)。现在的点对就是\((A_1,F_1,A_2,F_......
  • CSS 选择器优先级与继承规则详解
    CSS选择器优先级与继承规则详解在编写CSS时,理解选择器的优先级和继承规则是至关重要的。它们决定了样式如何应用到HTML元素上,尤其是在多个样式规则冲突时。本文将详细介绍CSS选择器的优先级和继承规则,帮助你更好地掌握样式的应用机制。CSS选择器优先级CSS选择器的优......