Ho scritto un programma che utilizza tutti i core disponibili utilizzando Parallel.ForEach
. L'elenco per ForEach
contiene ~ 1000 oggetti e il calcolo per ogni oggetto richiede un po 'di tempo (~ 10 sec). In questa configurazione scenario che un timer come questo:System.Timers.Timer gravemente inaccurato
timer = new System.Timers.Timer();
timer.Elapsed += TimerHandler;
timer.Interval = 15000;
timer.Enabled = true;
private void TimerHandler(object source, ElapsedEventArgs e)
{
Console.WriteLine(DateTime.Now + ": Timer fired");
}
Al momento il metodo TimerHandler
è uno stub per assicurarsi che il problema non è causato da questo metodo.
La mia aspettativa era che il metodo TimerHandler
fosse eseguito ogni ~ 15 secondi. Tuttavia, il tempo tra due chiamate a questo metodo raggiunge anche i 40 secondi, quindi 25 secondi in più. Utilizzando new ParallelOptions { MaxDegreeOfParallelism = Environment.ProcessorCount -1 }
per il metodo Parallel.ForEach
, ciò non accade e viene visualizzato l'intervallo previsto di 15 secondi.
È inteso che devo assicurarmi che ci sia sempre un core disponibile per ogni timer attivo? Sembra essere un po 'strano ancora di più, perché il "riservato" potrebbe essere una risorsa preziosa per il mio calcolo.
Modifica: come indicato da Yuval, l'impostazione di un minimo fisso di thread nel pool tramite ThreadPool.SetMinThreads
ha risolto il problema. Ho anche provato new ParallelOptions { MaxDegreeOfParallelism = Environment.ProcessorCount }
(quindi senza lo -1
nella domanda iniziale) per il metodo Parallel.ForEach
e anche questo risolve il problema. Tuttavia, non ho una buona spiegazione del perché queste modifiche abbiano risolto il problema. Forse ci sono stati così tanti thread creati che il thread del timer è stato "perso" per un tempo "lungo" fino a quando non è stato eseguito di nuovo.
Se si imposta in modo esplicito il numero di thread nel pool di thread prima di eseguire il ciclo parallelo, si verifica ancora? (Usando 'ThreadPool.SetMinThreads') –
stai pegging l'utilizzo del processore quando usi tutti i processori? in tal caso, tutti gli eventi risponderanno più lentamente a causa del modo in cui Windows elabora il pump dei messaggi. – Jeremy
Sospetto che il thread che esegue i thread paralleli (che probabilmente è lo stesso thread che esegue il timer) si blocchi. Se riesci a trovare un modo per eseguire il timer su un thread diverso, il tuo problema potrebbe andare via. Il thread che esegue il tuo timer potrebbe essere diverso a seconda di come è ospitata la tua app btw (ad esempio Windows form vs console app) –