您的位置:首页 > 产品设计 > UI/UE

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

2009-05-22 09:31 603 查看
开门见山,下面的例子中通过调用ThreadPool.QueueUserWorkItem(WaitCallback callBack, object state)的方式实现异步调用:

class Program
 { 
     static void Main(string[] args)
     {
          List<Action> actions = new List<Action>();
         actions.Add(() => Console.WriteLine("A1"));
         actions.Add(() => Console.WriteLine("A2"));
         actions.Add(() => Console.WriteLine("A3"));
         actions.Add(() => Console.WriteLine("A4")); 
  
         foreach (var action in actions)
         {
             ThreadPool.QueueUserWorkItem(state => action(), null);
         } 
  
         Console.Read();
     }
 }

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





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

class Program
 { 
     static void Main(string[] args)
     {
          List<Action> actions = new List<Action>();
         actions.Add(() => Console.WriteLine("A1"));
         actions.Add(() => Console.WriteLine("A2"));
         actions.Add(() => Console.WriteLine("A3"));
         actions.Add(() => Console.WriteLine("A4")); 
  
         foreach (var action in actions)
         {
             ThreadPool.QueueUserWorkItem(state => action(), null);
  
             Thread.Sleep(1);
         } 
  
         Console.Read();
     }
 }

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





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

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

所以正确的写法是:

foreach (var action in actions)
 {
 var a = action;
 ThreadPool.QueueUserWorkItem(state => a(), null);
 }
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: