2013-01-10 63 views
7

我想加載一個間隔進程隊列。換句話說,我有一個隊列,我希望隊列中的每個項目都能在一個單獨的時間間隔內運行。.net最大併發計時器線程

我的問題是,我似乎無法獲得超過25個線程在同一時間運行。我擁有的32768

默認的最大線程數64位計算機上使用.NET 4.5如何讓我的應用程序運行儘可能多的併發線程作爲我的機器可以處理?

下面是一個示例應用,在我的生產代碼複製的實際問題:

class Program 
{ 
    static void Main(string[] args) 
    { 
     System.Threading.ThreadPool.SetMaxThreads(200, 200); 
     test t = new test(); 

     t.LoadUrls("http://www.google.com"); 

     while (1 == 1) 
     { 
      System.Threading.Thread.Sleep(1000);//refresh every 5 seconds 
      Console.WriteLine(System.Diagnostics.Process.GetCurrentProcess().Threads.Count); 
     } 
    } 


    public class test 
    { 

     public void LoadUrls(string url) 
     { 
      for (int i = 0; i < 100; i++) 
      { 
       System.Threading.Timer t = new System.Threading.Timer(new System.Threading.TimerCallback(RunInterval), url, 0, 1000); 
       Console.WriteLine("Loaded {0} feeds.", i); 
      } 
     } 
     private static void RunInterval(object state) 
     { 
      string url = state as string; 
      string data = ""; 

      using (System.Net.WebClient cl = new System.Net.WebClient()) 
      { 
       Console.WriteLine("getting data for " + url); 
       data = cl.DownloadString(url); 
      } 

      //do something with the data 

     } 
    } 
} 

此代碼應理論上2秒鐘打完運行198個線程。

順便說一句,這個工作在優美的我的原型應用;它被寫入節點。但是,現在我不能讓它在C#中正常工作......

答: 問題是實際上的垃圾收集,並沒有一個線程池的問題在所有;游泳池不僅能夠後臺打印所有線程。訣竅是使用System.Threading.Timer的單個參數構造函數;這將使計時器使用自己作爲信號量,從而避免gc。

class Program 
{ 
    static void Main(string[] args) 
    { 
     for (int i = 0; i < 100; i++) 
     { 
      test t = new test(); 
      t.url = "http://www.google.com?" + i; 
      System.Threading.Timer ti = new System.Threading.Timer(new System.Threading.TimerCallback(t.RunInterval)); 
      ti.Change(0, 1000); 
     } 

     while (1 == 1) 
      System.Threading.Thread.Sleep(int.MaxValue); 
    } 


    public class test 
    { 
     public string url { get; set; } 
     public void RunInterval(object state) 
     { 
      Console.WriteLine("getting data for " + this.url); 
      string data = ""; 

      using (System.Net.WebClient cl = new System.Net.WebClient()) 
      { 
       data = cl.DownloadString(this.url); 
      } 
     } 
    } 
} 

我不確定爲什麼你會想要一個定時器由gc收集,但嘿我知道什麼。

+1

爲什麼你要這麼多線程在同一時間運行? –

+0

這是一個投票服務。它必須以指定的時間間隔輪詢n個Feed。我可以創建一個花哨的隊列系統並運行n個單獨的服務,每個服務只輪詢1個Feed。但是,我想要製作這個元素;我希望程序開始每個單獨的過程。 – Eulalie367

回答

5

如何使我的應用程序能像我的機器一樣運行儘可能多的併發線程?

這是錯誤的做法。每個線程都是昂貴的,創建幾百個,你的系統將嚴重降級。

您的代碼使用ThreadPool。該池具有限制線程數的算法。當你增加Sleep()次數時,你可能會看到更多的線程。

更直接的方式是設置ThreadPool.MinThreads。但期待更少的表現,而不是更多。

+0

這不是那麼昂貴......我有64GB的內存,但它永遠不會超過10MB。我希望它使用全部64GB。 你的建議是什麼? – Eulalie367

+0

此外,它永遠不會使用超過1%的可用CPU。 – Eulalie367

+0

我已經添加了一些建議,但仍然是錯誤的方法。 –

2

根據System.Threading.Timer

Use a TimerCallback delegate to specify the method you want the Timer to execute. The timer delegate is specified when the timer is constructed, and cannot be changed. The method does not execute on the thread that created the timer; it executes on a ThreadPool thread supplied by the system.

然後在System.Threading.Threadpool

There is one thread pool per process. Beginning with the .NET Framework 4, the default size of the thread pool for a process depends on several factors, such as the size of the virtual address space. A process can call the GetMaxThreads method to determine the number of threads. The number of threads in the thread pool can be changed by using the SetMaxThreads method. Each thread uses the default stack size and runs at the default priority.