C# Thread.Sleep(0)有什么用?
一、理论分析
回答这个要先从线程时间精度(时间片)开始说起。很多参考书说,默认情况下,时间片为15ms 左右,但是这是已经过时的知识。在老的 Windows 操作系统里,应用程序模式时时间片 15ms 左右,准确一点是15.625 左右。服务器模式是其双倍。但是在微软推行.Net 普及 Task之后,规则已经改动,并且做了精细的调节。现在Win10的时间精度为1ms(不用担心谷歌浏览器修改时间精度了),Win2013服务器的时间精度为7ms,使用微软提供的测试工具可以测出来:ClockRes - Sysinternals | Microsoft Learn
命令行:powercfg /energy
我们可以通过它可以更直观的看出:
因为有这个请求在,所以无论如何最低的计时器分辨率都只能为1ms。
所以,现在Win10 默认状态下,Sleep(1) 占时不再是15ms,而是1ms 左右:
1120us 即 1.12ms
下面现在正式回答,Thread.Sleep(0),Thread.Yield(),Thread.Sleep(1) 有什么不同:首先,Thread.Sleep 只是放弃时间片的剩余时间,让系统重新选择调度一个合适的线程(其优先级等于或者高于当前线程)。在没有其他活动线程的情况下,使用Sleep(0) 还是选上原来线程,即连任,如果连任了,系统不会对其做上下文切换,所以有:
由上面的图片可知耗时为18us左右,即0.018ms
其次,Thread.Yield() 是什么呢?跟 Thread.Sleep 有点像,但是它跟 Thread.Sleep(0) 有点区别:系统选择继任时可以选择优先级比原来低的线程。最后,Thread.Sleep(1) 是什么情况呢?前面说了,Thread.Sleep(0) 只是放弃时间片的剩余时间,让系统重新选择调度一个合适的线程。但是 Thread.Sleep(1) 却让当前线程沉睡了(即使只有1ms )。也就是说,主动放弃下次竞选,所以不可能连任,系统上下文必然发生切换(优先级低于原线程的家伙也有机会)。
二、最后总结一下Sleep(0)的用途
1)在图形界面程序中,使用Thread.sleep(0)可以避免长时间运行的任务阻塞UI线程的执行。例如在GUI程序中,当用户通过按钮点击或其他事件触发某个任务时,在该任务完成前可能需要等待某个数据加载、文件下载或其他操作完成。如果不使用Thread.sleep(0),就可能导致主线程阻塞而导致程序无响应。
2)在多线程爬虫程序中,使用Thread.sleep(0)可以有效地限制连接网站的频率,避免过于频繁访问同一目标网站而被封禁IP。例如,在高并发情况下,为了提高效率,某些爬虫程序会采用多线程方式进行网站抓取,这样往往需要控制每个线程之间的请求频率,以避免对目标网站造成负担或被视作恶意攻击。
3)在多线程程序中,使用Thread.sleep(0)可以优化线程调度算法,使得程序更加平滑和高效。例如在Java Web应用中,Tomcat服务器等Web容器采用线程池来管理客户端请求。为了避免某些线程占用关键资源导致其他线程无法响应,可以使用Thread.sleep(0)控制每个线程之间的竞争性,使得整个程序稳定、流畅地运行。
三、效率方面影响
Thread.Sleep(N)会严重影响当前线程中循环的运行效率,原因上面已经说明的很清楚了,上下文切换+线程竞争,所以在高速定时器的应用中:
1、Timer的Period小于10ms,精度会很差,Timer不能满足精度要求,在高速定时器中不推荐用Timer
Timer timer = new Timer(TimerCallback, null, 0, 2);
timer.Change(0, 2);long times = 0;
void TimerCallback(object sender)
{times++;Thread.Sleep(1);
}
运行一分钟后的结果:3767,远低于1000/2*60=30000
2、用for循环实现Timer的功能,不管是Task.Delay还是Thread.Sleep都实现不了小于10ms(>100HZ的精度)
1) 使用 Task.Delay 和 async/await:对于10ms以下精度不够
Delay(TimeSpan.FromMilliseconds(2), null);public async Task Delay(TimeSpan interval, Func<Task> func)
{while (true){await Task.Delay(interval);times++;}
}
运行一分钟后的结果:3729,远低于1000/2*60=30000
2)使用 Thread.Sleep:精度稍微好些,但是不够
DelaySleep();public async Task DelaySleep()
{Task.Run(() =>{while (true){Thread.Sleep(2);times++;}});
}
运行一分钟后的结果:19599,还是低于1000/2*60=30000
3、解决思路:Timer大时间里面写循环
DelayLoop(TimeSpan.FromMilliseconds(1000), func);public async Task DelayLoop(TimeSpan interval, Action func)
{while (true){await Task.Delay(interval);func();}
}private void func()
{for(int imm = 0; imm<500; imm++){Thread.Sleep(0);lock (this){times++;}}
}
运行一分钟后的结果:29000,稍微低于1000/2*60=30000,由于是手动一分钟后点击,没有写成一分钟自动停止,所以存在误差,有兴趣的同学可以测试下,可以满足高速定时器功能,已在项目中使用
参考资料:
1、(43 封私信) C# Thread.Sleep(0)有什么用? - 知乎 (zhihu.com)
2、https://blog.csdn.net/weixin_73077810/article/details/130519033
--以上。
相关文章:

C# Thread.Sleep(0)有什么用?
一、理论分析 回答这个要先从线程时间精度(时间片)开始说起。很多参考书说,默认情况下,时间片为15ms 左右,但是这是已经过时的知识。在老的 Windows 操作系统里,应用程序模式时时间片 15ms 左右࿰…...

二十四、【参考素描三大面和五大调】
文章目录 三种色面(黑白灰)五种色调 这个可以参考素描对物体受光的理解:素描调子的基本规律与素描三大面五大调物体的明暗规律 三种色面(黑白灰) 如下图所示,我们可以看到光源是从亮面所对应的方向射过来的,所以我们去分析图形的时候,首先要…...
【Python 千题 —— 基础篇】进制转换:十进制转二进制
题目描述 题目描述 计算机底层原理中常使用二进制来表示相关机器码,学会将十进制数转换成二进制数是一个非常重要的技能。现在编写一个程序,输入一个十进制数,将其转换成二进制数。 输入描述 输入一个十进制数。 输出描述 程序将输入的…...

[ spring boot入门 ] java: 错误: 无效的源发行版:17
因为我目前idea中使用的是jdK8,而在pom.xml文件里是17,所以我需要将所有地方修改为jdk8 pom.xml的jdk版本为8 maven的setting.xml文件 jdk为8 还有Java Compiler 还有Project Structure 里面的project 和 module...

【计算机组成体系结构】电路基本原理与加法器设计
一、算术逻辑单元—ALU 1.基本的逻辑运算(1bit的运算) 基本逻辑运算分为,与、或、非。大家应该很熟悉了,与:全1为1,否则为0。或:全0为0,否则为1。非:取反。三个基本的逻…...

MyBatisPlus之基本CRUD、常用注解
文章目录 前言一、MyBatisPlus简介1.简介2.特性 二、基本CRUD1.依赖2.搭建基本结构3.BaseMapper4.使用插入删除(1)通过id删除记录(2)通过id批量删除记录(3)通过map条件删除记录 修改查询(1&…...

采集EtherNET/IP转Profinet在西门子plc中的应用
远创智控网关YC-EIPM-PN,让你的设备和云平台实时连接! 远创智控YC-EIPM-PN网关产品支持各种数据接口,无论是工业领域的仪表、PLC、计量设备,还是设备数据,都能实时采集并整合。它将这些设备中的运行数据、状态数据等信…...
Paddle build_cinn_pass_test源码阅读(fluid目录下)
代码位置在 paddle\fluid\framework\paddle2cinn\build_cinn_pass_test.cc ,因为paddle CINN和PIR部分依旧在高频更新,所以各位看到的可能和我的不一样 inline bool CheckNodeExisted(const std::unordered_set<Node*>& nodes,const std::str…...

函数调用:为什么会发生stack overflow?
在开发软件的过程中我们经常会遇到错误,如果你用 Google 搜过出错信息,那你多少应该都访问过Stack Overflow这个网站。作为全球最大的程序员问答网站,Stack Overflow 的名字来自于一个常见的报错,就是栈溢出(stack ove…...
git log
git log -p 是一个用于显示git commit历史的命令,它会展示每个commit的详细信息,包括每个修改文件的清单、添加/删除的行所在的位置以及具体的实际更改。这个命令能够让用户深入了解仓库的历史记录。 与git log相比,git log -p 提供了更多的…...
在面试提问环节应该问那些内容
在面试提问环节应该问那些内容 薪资和福利: 你可以询问关于薪资、福利和其他福利待遇的细节,包括工资结构、健康保险、退休计划、带薪休假等。 了解关于加班、绩效奖金和涨薪机会的信息。 工作时间和灵活性: 询问工作时间、工作日和工作日…...
【vb.net】轻量JSON序列及反序列化
这个代码写的有点时间了,可能有点小bug,欢迎评论区反馈 作用是将Json文本转化成一个HarryNode类进行相关的Json对象处理或者读取,也可以将一个HarryNode对象用ToString变为Json文本。 举例: 1、读取节点数据 dim harryNode N…...

【Vue】vue2与netcore webapi跨越问题解决
系列文章 C#底层库–记录日志帮助类 本文链接:https://blog.csdn.net/youcheng_ge/article/details/124187709 文章目录 系列文章前言一、技术介绍二、问题描述三、问题解决3.1 方法一:前端Vue修改3.2 方法二:后端允许Cors跨越访问 四、资源…...

SpringSecurity + jwt + vue2 实现权限管理 , 前端Cookie.set() 设置jwt token无效问题(已解决)
问题描述 今天也是日常写程序的一天 , 还是那个熟悉的IDEA , 还是那个熟悉的Chrome浏览器 , 还是那个熟悉的网站 , 当我准备登录系统进行登录的时候 , 发现会直接重定向到登录页 , 后端也没有报错 , 前端也没有报错 , 于是我得脸上又多了一张痛苦面具 , 紧接着在前端疯狂debug…...

【21】c++设计模式——>装饰模式
装饰模式的定义 装饰模式也可以称为封装模式,所谓的封装就是在原有行为之上进行扩展,并不会改变该行为; 例如网络通信: 在进行网络通信的时候,数据是基于IOS七层或四层网络模型(某些层合并之后就是四层模型…...
【博客707】模版化拆解并获取victoriametrics的metricsql各个元素
golang解析victoriametrics的metricsql 场景: 需要拆解metricsql中的部分元素,比如:rollup function,label filter等需要对语法合法性进行判断,同时拒绝某些查询函数我们需要拆解metricsql并进行改造 使用victoriam…...
nodejs + express 实现 http文件下载服务程序
nodejs express 实现 http文件下载服务程序, 主要包括两个功能:指定目录的文件列表,某个文件的下载。 假设已经安装好 nodejs ; cd /js/node_js ; 安装在当前目录的 node_modules/ npm install express --save npm install express-gene…...
Qt多文本编辑器项目实战
0x00 引言 本文将详细讲解如何使用Qt实现一个多文本编辑器。涉及的话题包括:Qt框架基础、窗体布局、文本编辑、拓展功能等等。 在阅读本文之前,你需要掌握基本的C编程知识和Qt框架的使用方法。 0x01 新建Qt项目 在Qt Creator中,新建一个Q…...

CVE-2017-7529 Nginx越界读取内存漏洞
漏洞概述 当使用Nginx标准模块时,攻击者可以通过发送包含恶意构造range域的header请求,来获取响应中的缓存文件头部信息。在某些配置中,缓存文件头可能包含后端服务器的IP地址或其它敏感信息,从而导致信息泄露。 影响版本 Ngin…...
力扣每日一题136:只出现一次的数字
题目描述: 给你一个 非空 整数数组 nums ,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。 你必须设计并实现线性时间复杂度的算法来解决此问题,且该算法只使用常量额外空间。 示例 1 &#…...

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器的上位机配置操作说明
LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器专为工业环境精心打造,完美适配AGV和无人叉车。同时,集成以太网与语音合成技术,为各类高级系统(如MES、调度系统、库位管理、立库等)提供高效便捷的语音交互体验。 L…...

(LeetCode 每日一题) 3442. 奇偶频次间的最大差值 I (哈希、字符串)
题目:3442. 奇偶频次间的最大差值 I 思路 :哈希,时间复杂度0(n)。 用哈希表来记录每个字符串中字符的分布情况,哈希表这里用数组即可实现。 C版本: class Solution { public:int maxDifference(string s) {int a[26]…...

第19节 Node.js Express 框架
Express 是一个为Node.js设计的web开发框架,它基于nodejs平台。 Express 简介 Express是一个简洁而灵活的node.js Web应用框架, 提供了一系列强大特性帮助你创建各种Web应用,和丰富的HTTP工具。 使用Express可以快速地搭建一个完整功能的网站。 Expre…...

关于nvm与node.js
1 安装nvm 安装过程中手动修改 nvm的安装路径, 以及修改 通过nvm安装node后正在使用的node的存放目录【这句话可能难以理解,但接着往下看你就了然了】 2 修改nvm中settings.txt文件配置 nvm安装成功后,通常在该文件中会出现以下配置&…...

新能源汽车智慧充电桩管理方案:新能源充电桩散热问题及消防安全监管方案
随着新能源汽车的快速普及,充电桩作为核心配套设施,其安全性与可靠性备受关注。然而,在高温、高负荷运行环境下,充电桩的散热问题与消防安全隐患日益凸显,成为制约行业发展的关键瓶颈。 如何通过智慧化管理手段优化散…...
CRMEB 框架中 PHP 上传扩展开发:涵盖本地上传及阿里云 OSS、腾讯云 COS、七牛云
目前已有本地上传、阿里云OSS上传、腾讯云COS上传、七牛云上传扩展 扩展入口文件 文件目录 crmeb\services\upload\Upload.php namespace crmeb\services\upload;use crmeb\basic\BaseManager; use think\facade\Config;/*** Class Upload* package crmeb\services\upload* …...
3403. 从盒子中找出字典序最大的字符串 I
3403. 从盒子中找出字典序最大的字符串 I 题目链接:3403. 从盒子中找出字典序最大的字符串 I 代码如下: class Solution { public:string answerString(string word, int numFriends) {if (numFriends 1) {return word;}string res;for (int i 0;i &…...
OpenPrompt 和直接对提示词的嵌入向量进行训练有什么区别
OpenPrompt 和直接对提示词的嵌入向量进行训练有什么区别 直接训练提示词嵌入向量的核心区别 您提到的代码: prompt_embedding = initial_embedding.clone().requires_grad_(True) optimizer = torch.optim.Adam([prompt_embedding...

RNN避坑指南:从数学推导到LSTM/GRU工业级部署实战流程
本文较长,建议点赞收藏,以免遗失。更多AI大模型应用开发学习视频及资料,尽在聚客AI学院。 本文全面剖析RNN核心原理,深入讲解梯度消失/爆炸问题,并通过LSTM/GRU结构实现解决方案,提供时间序列预测和文本生成…...

Spring Cloud Gateway 中自定义验证码接口返回 404 的排查与解决
Spring Cloud Gateway 中自定义验证码接口返回 404 的排查与解决 问题背景 在一个基于 Spring Cloud Gateway WebFlux 构建的微服务项目中,新增了一个本地验证码接口 /code,使用函数式路由(RouterFunction)和 Hutool 的 Circle…...