難道調用ThreadPool.QueueUserWorkItem()的時候,真是必須調用Thread.Sleep(N)嗎?

原文地址爲:難道調用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: }

作者: Artech
出處: http://artech.cnblogs.com
本文版權歸作者和博客園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接,否則保留追究法律責任的權利。

轉載請註明本文地址:難道調用ThreadPool.QueueUserWorkItem()的時候,真是必須調用Thread.Sleep(N)嗎?
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章