难道调用ThreadPool.QueueUserWorkItem()的时候,真是必须调用Thread.Sleep(N)吗?

TMS320F28P550调试实录:从环境搭建到外设联调的避坑指南 在电机控制与数字电源等实时控制应用中,C2000系列DSP凭借其强大的定点和浮点处理能力,成为许多工程师的首选平台。然而,从拿到一颗新芯片到真正跑通程序,中间隔着环境配置、启动流程、外设调试等多道关卡。TMS320F28P550作为C2000家族F28P55x系列的一员,沿用了C28x内核与硬件浮点单元,同时集成了ePWM、ADC、CAN等丰富外设,适用于高性能电机驱动与伺服系统。在实际开发中,CCS版本搭配、仿真器连接、Flash烧写失败、Boot模式选择、看门狗异常复位等问题常常让人陷入困境。本文以TM 阅读详情

来自:http://www.cnblogs.com/artech/archive/2009/05/22/1486761.html 

开门见山,下面的例子中通过调用ThreadPool.QueueUserWorkItem(WaitCallback callBack, object state)的方式实现异步调用:

   1: class Program
   2: { 
   3:     static void Main(string[] args)
   4:     {
   5:          List<Action> actions = new List<Action>();
   6:         actions.Add(() => Console.WriteLine("A1"));
   7:         actions.Add(() => Console.WriteLine("A2"));
   8:         actions.Add(() => Console.WriteLine("A3"));
   9:         actions.Add(() => Console.WriteLine("A4")); 
  10:  
  11:         foreach (var action in actions)
  12:         {
  13:             ThreadPool.QueueUserWorkItem(state => action(), null);
  14:         } 
  15:  
  16:         Console.Read();
  17:     }
  18: } 

但是出现错误的输出结果:

image

解决的方案就是在每次For循环中,调用Thread.Sleep休眠当前线程,哪怕是1ms:

   1: class Program
   2: { 
   3:     static void Main(string[] args)
   4:     {
   5:          List<Action> actions = new List<Action>();
   6:         actions.Add(() => Console.WriteLine("A1"));
   7:         actions.Add(() => Console.WriteLine("A2"));
   8:         actions.Add(() => Console.WriteLine("A3"));
   9:         actions.Add(() => Console.WriteLine("A4")); 
  10:  
  11:         foreach (var action in actions)
  12:         {
  13:             ThreadPool.QueueUserWorkItem(state => action(), null);
  14:  
  15:             Thread.Sleep(1);
  16:         } 
  17:  
  18:         Console.Read();
  19:     }
  20: }
  21:  

这次能够输出正确的结果:

image

我们也看到很多人确实是这么做的。但是如果真是必须这样的话,这样的编程方式很难让我接受,不知道大家有何高见。

在老赵的提示下,醒悟过来:由于被置于ThreadPool中的操作时异步的,还没有来的执行的时候,action已经被for循环改变,永远是同一个action对象! 呵呵,脑袋有时候有点转不过弯!

所以正确的写法是:

   1: foreach (var action in actions)
   2: {
   3: var a = action;
   4: ThreadPool.QueueUserWorkItem(state => a(), null);
   5: }

作者: Artech
出处: http://artech.cnblogs.com
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

 

C#线程模型深度解析:从ThreadPool饥饿到async/await真异步 线程是.NET并发编程的底层基石,其本质是操作系统调度的基本单元,涉及栈内存分配、上下文切换与内核对象竞争等物理成本。理解线程模型的关键在于厘清Thread、ThreadPool与Task三者的分层关系:原始Thread开销大且危险;ThreadPool通过复用降低创建成本,但存在饥饿与过度配置风险;而Task和async/await并非自动异步,其性能价值取决于是否真正基于IOCP或完成端口的‘真异步’实现。技术价值体现在避免UI冻结、防止ThreadPool耗尽、提升I/O密集型服务吞吐。典型应用场景包 阅读详情

相关推荐

C#线程池底层原理与生产调优实战

线程池是.NET中实现高并发任务调度的核心基础设施,其本质是基于Windows内核线程池的对象池化机制,通过预分配、复用和智能回收线程资源,解决创建销毁开销大与CPU/内存资源有限之间的矛盾。它并非简单的异步执行容器,而是融合了任务队列管理、执行上下文传递、I/O完成端口协同等操作系统级能力的资源代理。在实际应用中,ThreadPool直接影响API响应延迟、GC压力与突发流量承载能力,尤其在微服务、实时风控、金融行情等低延迟场景中,合理配置MinThreads、理解QueueUserWorkItem的内存

xiang_fu的博客 644

C# 异步多线程入门到精通之ThreadPool篇

c#教程​https://www.cnblogs.com/Yesi/p/15829200.html ​ ThreadPool是.net2.0时代的产物,有了Thread为什么还会有ThreadPool呢?ThreadPool可以做到限制线程数量、重用线程 启动线程池线程 ThreadPool 提供的 API 相对于 Thread 是比较少的,在 ThreadPool 中需使用 QueueUserWorkItem 方法,来启动一个线程 例如:Dosome 是个普通的方法...

chinaherolts2008的博客 2384

C#线程底层原理与高并发实战避坑指南

线程是操作系统调度的最小执行单元,其本质是CPU时间片的虚拟化抽象,而非物理并行加速器。理解线程需穿透async/await语法糖,回归Thread类、上下文切换、内存屏障与伪共享等底层机制。线程性能瓶颈常源于盲目创建、错误同步(如volatile缺失)、锁粒度过粗或ThreadPool误用,而非单纯数量不足。在.NET开发中,正确使用ThreadLocal、Interlocked原子操作、CancellationToken协作取消及ThreadPool线程复用,可显著提升UI响应性、Web API吞吐量与

baochuanying9531的博客 3243

ThreadPool.QueueUserWorkItem引发的血案,线程池异步非正确姿势导致程序闪退的问题...

 ThreadPool是.net System.Threading命名空间下的线程池对象。使用QueueUserWorkItem实现对异步委托的先进先出有序的回调。如果在回调的方法里面发生异常则应用程序会出现闪退。当然是指不处理那个异常的情况下。这不公司的CMS在生产环境频频出现闪退的情况。该死的是,原来用老机器配置不高的情况下没有出现过。换了更好的新机器后出现的。 ...

weixin_34216107的博客 1704

C#线程池原理与实战调优:从资源开销到生产级稳定性

线程池是.NET并发编程的核心基础设施,本质是对有限线程资源的高效复用机制。其底层基于CLR的全局队列+本地队列双层任务分发、启发式自适应扩容算法及后台线程生命周期管理,解决了线程创建开销大(300–800μs/次)、堆栈内存占用高(1–2MB/线程)和上下文切换频繁等关键问题。技术价值在于规避线程爆炸与线程泄漏,支撑高并发API网关、实时数据管道和金融交易系统等场景的稳定运行。本文聚焦C#线程池在真实生产环境中的配置调优、异常处理、IO/CPU任务分流及监控告警实践,涵盖Task.Run、ThreadPo

didi9310的博客 429

C# ThreadPool.QueueUserWorkItem典型案例详解

今天在博客园拜读了   蒋金楠,难道调用ThreadPool.QueueUserWorkItem()的时候,真是必须调用Thread.Sleep(N)吗?自己也深有启发,决定再次陈述个人理解。  我自己差不多写了一段源码,类似蒋金楠那篇博文中的:using System;using System.Collections.Generic;using System.Threading;namespac

霍力强的专栏 3万+

ThreadPool.QueueUserWorkItem的性能问题

在WEB开发中,为了减少页面等待时间提高用户体验,我们往往会把一些浪费时间的操作放到新线程中在后台运行。 简单的实现代码就是: //代码一 new Thread(()=&gt;{ //do something }).Start(); 但是对于一个请求量大的网址这样做是很不现实的——每一个操作都要开启一个新线程,最终会因CPU不堪重负而使网站挂掉。 更好的做法是使用线程队列。 ...

jandroid 947

RK3588 EVB开发板原理图讲解【六】

该原理图展示了eMMC Flash与主控芯片之间的连接关系,以及相关的电源、信号线路和去耦电容等。

weixin_48721556的博客 1162

[原创] 难道调用ThreadPool.QueueUserWorkItem()的时候,真是必须调用Thread.Sleep(N)吗?

开门见山,下面的例子中通过调用ThreadPool.QueueUserWorkItem(WaitCallback callBack, object state)的方式实现异步调用: 1: class Program 2: { 3: static void Main(string[] args) 4: { 5: List acti

artech的专栏 2022

2006NOIP普及组真题 4. 数列

从上述推理中,我们发现要输出的幂次和中的第 N 项(也就是幂次和中的序号N),对应的二进制位数和幂次和对应的二进制位数相同。当 k=3 时,k的幂次为1, 3, 9, 27, 81…,即第0位,第2位均为1,转成 k 进制(k=3)时。,即第2位,第3位均为1,转成 k 进制(k=3)时。转成 k 进制(k=3)时的幂次和为。,即第0位,第1位,第2位均为1,(即第0位,第1位,第2位均为1)N=12时,12的二进制是。(即第0位,第2位均为1)(即第2位,第3位均为1)结论:这道题就变成了。

weixin_40252159的博客 1513

PowerBI参数化实战:3分钟搞定动态数据源切换(附常见错误排查)

本文详细介绍了PowerBI参数化实战技巧,教你3分钟实现动态数据源切换。通过创建参数、改造查询和测试切换三步,轻松应对多环境部署与团队协作中的路径问题,并附上常见错误排查指南,有效提升报表的可维护性和工作效率。

p1q2r的博客 585

难道调用ThreadPool.QueueUserWorkItem()的时候,真是必须调用Thread.Sleep(N)吗?...

开门见山,下面的例子中通过调用ThreadPool.QueueUserWorkItem(WaitCallback callBack, object state)的方式实现异步调用: 1: class Program 2: { 3: static void Main(string[] args) 4: { ...

weixin_33729196的博客 142

扫地机的CPU只要二十多块?2024第二拆来了

昨天还说到这个机器人的故障,经小鱼拆机后测试和后台网友留言确认,不是防跌落问题,是轮子故障,这个轮子不会动,轮子上有一个限位开关检测机器人是否离开地面的,测试的时候也没有误触发,所以电机存在故障,后面拆电机的时候再检查。最后再留下一个疑问,这个机器人的回充没有用红外管,机器人是如何识别基站进行返回充电的(因为只买了本体,没买充电桩,不确定充电桩的形状,是不是利用点云识别不确定)懂的请留言。全志的R16,封装是 BGA282,那这个板子至少是4层板,小鱼盲猜 6 层板,知道的小伙伴欢迎留言。

生活不止眼前的苟且 1974

Microchip Studio 7烧录AVR单片机全流程:熔丝位配置与芯片锁死恢复指南

单片机开发中,程序烧录与熔丝位配置是决定系统稳定性的关键环节。对于AVR系列单片机,ISP烧录协议提供了一种灵活的在线编程方式,而熔丝位则控制着芯片的时钟源、复位引脚等底层硬件配置。错误的熔丝位设置可能导致芯片锁死,此时需要借助外部时钟或高压编程器进行恢复。本文基于Microchip Studio 7,详细讲解AVR单片机的烧录流程、熔丝位避坑指南以及常见故障排查方法,帮助开发者避免踩坑。

weixin_33895695的博客 432

飞牛fnNAS搭建个人小账本

本文介绍了如何在飞牛NAS上部署ezBookkeeping个人记账应用。该开源工具支持多平台使用,具备双因素认证、多级分类等功能。文章详细讲解了Docker激活、镜像下载、容器部署等步骤,并展示了账户管理、交易记录等基础操作。同时指导用户通过ZeroTier实现远程访问,方便随时随地使用个人记账系统。该方案既保障了数据隐私,又提供了专业记账功能,适合对财务隐私敏感的用户。

dgnankai的专栏 781

AXI总线详解完结篇

经过几个月的整理和发文,AXI总线详解系列正式迎来最终篇,内容基本涵盖了上一篇文章的全部内容。 所有文章的链接如下: 1、 AXI总线详解 2、AXI总线详解-总线和接口以及协议 3、AXI协议中的通道结构 4、AXI总线详解-AXI4读写操作时序及AXI4猝发地址及选择 5、AXI4交换机制 6、ZYNQ中DMA与AXI4总线-DMA简介 7、AXI总线详解-不同类型的DMA 8、AXI总线详解-DMA内部寄存器的读写方式 9、AXI总线详解-几种应用DMA的场合 10、Altera Scatter-G.

OpenFPGA的博客 5484

[原创] 难道调用ThreadPool.QueueUserWorkItem()的时候,真是必须调用Thread.Sleep(N)吗?...

开门见山,下面的例子中通过调用ThreadPool.QueueUserWorkItem(WaitCallback callBack, object state)的方式实现异步调用: 1: class Program &lt;!--CRLF--&gt; 2: { &lt;!--CRLF--&gt; 3: static void Main(string[] args) &l...

威尔软件 124

完整复盘【避雷jd文职某岗位】潍坊青州hhj(据说未来搬到天津),助理实验师岗位,三人进面,面试全部不及格,空头岗位!像这种情况,该单位很多 | 附个人完整备考背诵题目 | 世间一场梦,不会再考这个了

本文以博主本人报考jun dui文职,从报考、备考、考试、查成绩到资格审查、面试,全程亲身经历,给想要报考该内容的朋友们一些小的参考。祝你顺利上岸!完整复盘【避雷jd文职某岗位】潍坊青州hhj(据说未来搬到天津),助理实验师岗位,三人进面,面试全部不及格,空头岗位!像这种情况,该单位很多 | 附个人完整备考背诵题目 | 世间一场梦,不会再考这个了

追光者♂:记录、分享、总结、提升,现象级专栏《Python从入门到人工智能》作者,无惧黑暗,坚信曙光 245

C#多线程编程实战:从Thread到async/await的并发开发指南

多线程编程是现代软件开发中提升应用性能与响应能力的关键技术,其核心原理在于通过并发执行充分利用多核CPU的计算资源。在C#开发中,从基础的Thread类到现代的Task与async/await模型,提供了不同层次的并发抽象。掌握线程同步机制如锁(lock)、信号量(Semaphore)以及线程安全集合,是确保数据一致性与避免竞态条件的基础。这些技术对于构建高并发的后端服务、响应迅捷的桌面应用以及实时数据处理系统具有重要价值。本文聚焦于C#多线程编程的完整知识体系,深入探讨了线程池管理、异步编程模式以及并行处

weixin_33912453的博客 301

使用Captum库对CIFAR数据集进行模型可解释性分析

为了训练模型,我们需要指定损失函数和优化技术。损失函数用于衡量模型的性能,在训练过程中,我们通过调整模型参数来最小化损失。本教程使用。

2501_90323865的博客 177

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

.NET异步机制深度解析:从async/await到IOCP的运行时真相

async/await是.NET中实现高并发I/O的核心语法机制,其本质并非多线程编程,而是编译器驱动的状态机与运行时调度协同的结果。它依托Task作为异步契约载体,通过SynchronizationContext控制续体执行上下文,并深度依赖Windows底层IOCP完成端口实现零阻塞I/O。这种设计使少量线程即可支撑海量并发请求,显著提升吞吐与资源利用率。典型应用场景包括Web API服务(如Kestrel)、支付网关、实时数据采集等I/O密集型系统。理解其原理对规避死锁、线程饥饿、上下文捕获陷阱等生产

didi9310的博客 492

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

上一篇: How to synchronize access to a shared resource in a multithreading environment by using Visual C#
下一篇: 获得微博的URL中的MID
ArvinStudy
博客等级 码龄15年 83粉丝 193原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值