2009-06-06 1 views
6

Esistono diversi thread nella mia applicazione che funzionano in background. Si connettono al database ed eseguono alcune query selezionate che richiedono tempo. Nella maggior parte dei casi queste query restituiscono solo diversi record. Di volta in volta, tuttavia, possono restituire decine di migliaia di record. Tutti questi vengono quindi elaborati in un ciclo.Delphi - regolazione del tempo di sospensione del thread

Poiché tale situazione può verificarsi in diversi thread allo stesso tempo, non voglio la mia applicazione per utilizzare il 100% del tempo di CPU quando quei fili sono l'elaborazione dei dati; né voglio fare in modo che tutti i thread combacino per il tempo del processore. Pertanto chiamo la funzione Sleep() in ogni iterazione dei loop in quei thread.

Non so, tuttavia, come regolare il tempo di sospensione. Non voglio che i cicli durino per sempre, quindi il periodo di sonno non può essere troppo lungo. L'ho impostato su 2 millisecondi in ogni iterazione (in ogni thread) (perché 2ms? - questa è una buona domanda :)).

Ho pensato, d'altra parte, che potrei prolungare il tempo di sonno, ma chiamare il sonno solo una volta ogni iterazioni (diciamo, Sleep (100) ogni 50 iterazioni). Quale approccio dovrei scegliere? Una singola iterazione dei loop richiede circa 30 ms ciascuno (senza alcun sonno).

Si prega di avvisare.

Grazie!
Mariusz.

risposta

9

Chiamare Sonno() non ha senso. Usa tutta la potenza di elaborazione che puoi ottenere e lascia che il sistema elabori come programmare al meglio i tuoi thread. Chiamare Sleep() causerà solo interruttori di contesto aggiuntivi e ridurrà il throughput. Se l'elaborazione in background interferisce con il thread principale o altre applicazioni, quindi abbassa di conseguenza la priorità dei thread in background.

Se si vuole lasciare che le discussioni dormire per limitare la quantità di dati che generano per i consumatori, guardare in produttore-consumatore-code. Fai in modo che le discussioni del produttore si blocchino semplicemente quando la loro coda è piena, in questo modo non ti servirà affatto a giocherellare con i tempi.

Si noti inoltre che l'utilizzo della CPU massima è generalmente una buona cosa, specialmente sui processori moderni. Anche su laptop che hanno un breve tempo di carico elevato è meglio che prolungare artificialmente il tempo richiesto dall'attività, poiché il processore/l'intero sistema sarà presto in grado di immettere stati di alimentazione più bassi.

+0

Ma se questo viene eseguito in background su un computer che dispone anche di qualcuno che lavora su (ad esempio scrivere un foglio di calcolo), non lo fai vuoi che il processo in background renda il processo in foreground inutilizzabile. – dummzeuch

+2

Vero, ma è per questo che ho scritto che la priorità del thread in background può essere ridotta, mantenendo le altre app (o il thread principale) reattive mentre si utilizza ancora il potenziale completo del sistema. Sui sistemi moderni (multi-core) mantenere tutti i core sufficientemente caricati è molto più un problema della mancanza di reattività dell'applicazione in primo piano. E l'enorme I/O non ottimizzato è una minaccia molto più grande per l'usabilità di un sistema rispetto al carico elevato della CPU, comunque. – mghie

2

Potrebbero esserci approcci migliori rispetto all'utilizzo del sonno per controllare i thread. Poiché la chiamata al database può restituire 1-1000 di record per l'elaborazione, potrebbe essere sensato separare l'applicazione in due livelli, magari utilizzando una coda di messaggi per memorizzare le richieste. L'app potrebbe richiamare un servizio dati e il servizio dati eseguirà quindi la query e invierà singoli messaggi di dati (o blocchi di messaggi, ecc.) A una coda. La tua app può quindi creare tutti i thread necessari per elaborare i messaggi. Più thread significa elaborazione più rapida a spese della CPU, ma è possibile regolarlo per ottenere il giusto equilibrio.

3

È meglio solo fare le discussioni a bassa priorità e far loro lavorano senza posti letto, altrimenti non si utilizza tutta la potenza della CPU. Ad esempio su sistemi multi-core/multi-cpu. O se il tuo sistema è al 100% inattivo: perché aspettare o dormire?

Ma se avete bisogno di alcuni posti letto tuttavia, notare che il sonno (1) attende 10-15ms (!) A causa del timeslice predefinita di Windows. È possibile utilizzare timeBeginPeriod (1) dell'unità MMSystem.pas per impostare la risoluzione su 1 ms :-) (l'ho usato per la comunicazione seriale).

0

utilizza TThread.Sleep() da System.Classes, anziché Sleep() da WinApi.Finestre

// Winapi.Windows contains GetTickCount and Sleep 
// System.Classes contains TThread (universal option) // TThread.GetTickCount() // TThread.Sleep() 
uses System.Types, System.Classes, Vcl.Forms; 

// poi nel processo utilizzare la seguente

TThread.Sleep(0); 

Application.ProcessMessages(); // clear all Vcl messages // part of Vcl.Forms 
CheckSynchronize(); // check all threaded events