难道调用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: } 

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

解决的方案就是在每次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:  

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

 

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

在老赵的提示下,醒悟过来:由于被置于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
如果你想及时得到个人撰写文章以及著作的消息推送,或者想看看个人推荐的技术资料,可以扫描左边二维码(或者长按识别二维码)关注个人公众号(原来公众帐号蒋金楠的自媒体将会停用)。
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

原文链接

时间: 2024-09-20 00:43:47

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

C# ThreadPool.QueueUserWorkItem典型案例详解

  using System; using System.Collections.Generic; using System.Threading; namespace ThreadPoolTest { class Program { static void Main(string[] args) { //声明一个Action委托的List,添加一些委托测试用 List actions = new List { ()=>{Console.WriteLine("A-1");}, ()

jna-JNA调用C/C++的方法,怎么调用下面的方法?

问题描述 JNA调用C/C++的方法,怎么调用下面的方法? BOOL NET_DVR_PlayBackControl_V40( LONG lPlayHandle, DWORD dwControlCode, LPVOID lpInBuffer, DWORD dwInLen, LPVOID lpOutBuffer, DWORD *lpOutLen ); 上面是C++/C 中的方法,其中倒数第2和倒数第4个参数,API上介绍说是指针. 我在调用这个方法的时候第4个参数要求要的数据如下: NET_DVR

android-Android 调用系统相机的问题:怎么调用系统相机实现连续拍照

问题描述 Android 调用系统相机的问题:怎么调用系统相机实现连续拍照 调用系统相机只能拍一张照片就返回了~能不能多拍几张再返回的常量 解决方案 在实现拍照的功能时遇到了很多问题,搜索了很多资料,尝试了很多办法,终于解决了,下面简要的描述下在开发过程中遇到的问题. 虽然之前看过android开发的书,但是没有做过东西,这次也是临时决定让我做一个android采集系统的演示程序.拍照是其中一个功能,让网搜索了下拍照有两种方式,其中一种就是调用系统相机实现拍照功能. 启动照相机进行拍照,代码如下

java-php调用3Dweb项目j改为ava调用3Dweb项目

问题描述 php调用3Dweb项目j改为ava调用3Dweb项目 现在正在做一个网站,里面需要嵌入3d的车模型,使用3d Max实现的,手头上有一个用PHP调用3d车模的源码,怎么改为用java来调用...求各位大神帮帮忙

delphi-求救!!! 调用一个DLL文件的函数,提供的调用方法好像是Delphi,VB怎么调用!

问题描述 求救!!! 调用一个DLL文件的函数,提供的调用方法好像是Delphi,VB怎么调用! 提供的调用方法如下 3.2 封装模式 接口动态库的文件名为nxmi.dll,HIS直接调用nxmi.dll, 调用之前请先安装读卡环境,安装程序为inst.exe. 3.3 调用方法 对外提供的接口函数: Procedure invoke(params :PChar; result : PChar) ; 我现在在VB中写的如下: 在模块下定义 Public Declare Function invo

学习-安卓中BaseAdapter是如何调用getView()方法的在哪里开始调用

问题描述 安卓中BaseAdapter是如何调用getView()方法的在哪里开始调用 最近学习BaseAdapter很苦恼虽然会用,但不知道它内部实现的原理请问大牛它是如何工作的呢 好人一生平安 解决方案 baseadapter getcout调用getview没有被调用 解决方案二: http://jcodecraeer.com/a/anzhuokaifa/androidkaifa/2014/1021/1815.html

如何在调用CAD,并在CAD中调用lisp时不弹出CAD界面?全部执行后再显示?

问题描述 如何在调用CAD,并在CAD中调用lisp时不弹出CAD界面?全部执行后再显示?我是这样做的AutoCAD.AcadApplicationClasscadApp=newAutoCAD.AcadApplicationClass(); //2004.2005Application.DoEvents();//cadApp.Documents.Application.Visible=true;//CAD成图cadApp.Documents.Open(sFileName,falseasobjec

集群 ejb-websphere8.5.5上的应用通过EJB调用weblogic8.1上的应用,调用不通

问题描述 websphere8.5.5上的应用通过EJB调用weblogic8.1上的应用,调用不通 各位大牛好,目前项目遇到了一个比较棘手的问题,想请求一下各位大牛,万分感谢.我们的项目是部署在websphere8.5.5上,JDK是1.6,集群有4台服务器,通过EJB调用Weblogic8.1上的应用,JDK是1.4,投产后,有时4台服务器会有一台可以连通到weblogic上的应用,有时候都连不能连能,并且报org.omg.CORBA.ORBPackage.InvalidName: Loca

c#调用pb写的dll无法正常调用

问题描述 c#调用pb写的dll无法正常调用 现在c#调用pb写的dll,我用winform可以正常调用而用webform调用显示找不到函数的入口,请问大神们怎么解决这个问题 解决方案 两者加载dl 的路径,以及依赖项有区别吧. webform在浏览器上,路径等不是本地路径.还有权限控制等也要考虑