2013-01-10 16 views
7

Sto tentando di caricare una coda di processi a intervallo. In altre parole, ho una coda e voglio che ogni elemento della coda venga eseguito su un singolo intervallo.. Thread max simultanei timer timer

Il mio problema è che non riesco a ottenere più di 25 thread da eseguire contemporaneamente. Sto usando .Net 4.5 su una macchina a 64 bit che ha un conteggio massimo predefinito di 32768.

Come faccio a far funzionare la mia app come molti thread simultanei che la mia macchina può gestire?

Ecco un'applicazione di esempio che riproduce il vero problema nel mio codice di produzione:

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 

     } 
    } 
} 

Questo codice dovrebbe teoricamente funzionare 198 le discussioni dopo 2 secondi o giù di lì.

A proposito, questo ha funzionato magnificamente nella mia app prototipo; è stato scritto nel nodo. Ma, ora non posso farlo funzionare correttamente in C# ...

RISPOSTA: Il problema era in realtà con la raccolta dei rifiuti e non è stato un problema di thread a tutti; la piscina è più che capace di spoolare tutti i fili che sto lanciando. Il trucco è usare il costruttore di parametri singolo di System.Threading.Timer; questo farà sì che il timer si usi come un semaforo, evitando così 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); 
      } 
     } 
    } 
} 

io non sono sicuro perché si vorrebbe mai un timer da riscuotere da parte del GC, ma hey che ne so io.

+1

Perché vuoi tanti thread in esecuzione allo stesso tempo? –

+0

Questo è per un servizio di polling. Deve eseguire il polling di n feed a intervalli specificati. Potrei creare un fantastico sistema di coda ed eseguire n singoli servizi che eseguono solo il polling di 1 feed per servizio. Ma vorrei fare questo meta; Vorrei che il programma iniziasse ogni singolo processo. – Eulalie367

risposta

5

Come posso fare in modo che la mia app esegua tutti i thread simultanei che la mia macchina può gestire?

Questo è l'approccio sbagliato. Ogni thread è costoso, crea poche centinaia e il tuo sistema si degraderà seriamente.

Il codice utilizza il ThreadPool. Il pool ha un algoritmo per limitare il numero di thread. Quando aumenti i tempi di Sleep() potresti vedere qualche altro thread.

Un modo più diretto sarebbe quello di impostare ThreadPool.MinThreads. Ma aspettati meno prestazioni, non di più.

+0

Non è così costoso ... Ho 64 GB di RAM con cui lavorare, ma non supera mai i 10 MB.Voglio che utilizzi tutti i 64 GB. Quale sarebbe il tuo suggerimento? – Eulalie367

+0

Inoltre, non utilizza mai più dell'1% della mia CPU disponibile. – Eulalie367

+0

Ho aggiunto alcuni suggerimenti ma è ancora l'approccio sbagliato. –

2

Secondo 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.

Poi nel 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.