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

简介:

开门见山,下面的例子中通过调用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: }


作者:蒋金楠
微信公众账号:大内老A
微博: www.weibo.com/artech
如果你想及时得到个人撰写文章以及著作的消息推送,或者想看看个人推荐的技术资料,可以扫描左边二维码(或者长按识别二维码)关注个人公众号(原来公众帐号 蒋金楠的自媒体将会停用)。
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
相关文章
大模型应用开发-LangChain入门教程
大模型应用开发-LangChain入门教程
597 0
|
存储 人工智能 分布式计算
2021云栖大会丨阿里云发布第四代神龙架构,提供业界首个大规模弹性RDMA加速能力
10月20日,2021年杭州云栖大会上,阿里云发布第四代神龙架构,升级至全新的eRMDA网络架构,是业界首个大规模弹性RDMA加速能力。
2021云栖大会丨阿里云发布第四代神龙架构,提供业界首个大规模弹性RDMA加速能力
|
C#
C#清除DataGridView数据DataGridView中的“无法删除未提交的新行”
C#清除DataGridView数据DataGridView中的“无法删除未提交的新行”
1717 0
C#清除DataGridView数据DataGridView中的“无法删除未提交的新行”
|
安全 网络安全 数据库
Kali渗透测试:使用工具Metasploit攻击操作系统(一)
Kali渗透测试:使用工具Metasploit攻击操作系统(一)
884 0
|
小程序 算法 Go
Golang微信小程序数据解密报错:invalid character “‘p‘“ looking for beginning of value
Golang微信小程序数据解密报错:invalid character “‘p‘“ looking for beginning of value
743 0
|
数据库
开源数据集——行人数据
开源数据集——行人数据
4241 0
开源数据集——行人数据
|
算法 API 开发者
【Qt UI相关】Qt中如何控制 窗口的最大化、最小化和关闭按钮?一文带你掌握用法
【Qt UI相关】Qt中如何控制 窗口的最大化、最小化和关闭按钮?一文带你掌握用法
3234 1
|
安全 Linux
Linux系统中普通用户获取root权限
Linux系统中普通用户获取root权限
1067 0
|
Arthas 监控 Java
【监控系统】Arthas
Arthas 是阿里巴巴开源项目,他是一款线上监控诊断产品,通过全局视角实时查看应用 load、内存、gc、线程的状态信息,并能在不修改应用代码的情况下,对业务问题进行诊断,包括查看方法调用的出入参、异常,监测方法执行耗时,类加载信息等,大大提升线上问题排查效率。
550 0
【监控系统】Arthas
|
缓存 安全 数据安全/隐私保护
CleanMyMac X订阅版使用到期 如何免费永久使用?
cleanmymac支持一键智能清理垃圾,能够帮助用户将Mac恢复到最好的状态,是每一个苹果电脑用户都应该有的一个软件,CleanMyMac是集所有功能于一身的先进程序卸载清理器,只需两个简单步骤就可以把系统里那些乱七八糟的无用文件统统清理掉,节省宝贵的磁盘空间。支持清理Mac系统中多余的语言包、系统缓存、程序,有效帮助苹果系统进行瘦身工作。
1159 0