萬盛學電腦網

 萬盛學電腦網 >> 網絡編程 >> 編程語言綜合 >> C# ThreadPool.QueueUserWorkItem典型案例詳解

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");},

  ()=>{Console.WriteLine("A-2");},

  ()=>{Console.WriteLine("A-3");},

  ()=>{Console.WriteLine("A-4");}

  };

  //遍歷輸出結果

  foreach (var action in actions)

  {

  ThreadPool.QueueUserWorkItem(state => action() , null);

  }

  Console.ReadKey();

  }

  }

  }

  這個很意外的結果如下:

C# ThreadPool.QueueUserWorkItem典型案例詳解 三聯

  為什麼如此呢:

  我分析下,首先大家都知道創建一個線程是需要時間的,線程池作為一個管理線程的對象操作簡單,但是涉及到具體細節的時候卻很難控制,其原理是當線程池收到請求以後,則從線程池中找到一個閒的線程分配給它,然後啟動。 但是線程池的線程從創建到啟動需要時間,但是主線程的循環顯然只是瞬間完成,完全沒必要夾雜在線程池的等待中,因此出現了主線程執行完循環最後是的線程池收到的請求委托是列表中的最後一個,如何解決?

  方式一: Thread.Sleep(1);

  博主說對於Thread.Sleep(N)的方式難以接受,其實只要細細去分析原理,就能知道這個方式是可以接受甚至是微妙的,Thread.Sleep(N)是對當前線程阻塞一定時間,那這個處理不論是主線程還是線程池中的線程都是有效果的,至少為線程池中的線程的請求與啟動贏得了時間。當然在這裡阻塞的線程一定是主線程,使其不能得到CPU時間,這樣也就成功了得到預期結果。

  後來又采取另外一種方式,

  方式二:

  foreach (var action in actions)

  {

  var Tempaction = action;

  ThreadPool.QueueUserWorkItem(state => Tempaction() , null);

  }

  將循環中的變量存儲到一個臨時變量中,為什麼這樣行呢?

  大家知道線程池是有請求就為其分配一個自由線程與其工作,當每一次循環中的變量不同也就是對象不同時這時候每次請求出現差異,當然線程池必須為每一個做准備,不同於把循環變量直接作為請求,這時候每一個請求就按順序依次准備好依次啟動。當然也就成功了。

copyright © 萬盛學電腦網 all rights reserved