Dopo aver letto vari articoli, esercitazioni e post di MSDN qui ho trovato un progetto per un servizio di Windows che volevo assicurarmi che la mia strategia di threading fosse corretta e che non porti a problemi di memoria, CPU, database.
Ecco il flusso di base.
MAIN THREAD
- Raccogli l'elenco dei servizi da caricare.
- Carica ogni servizio.
SERVICE THREAD (avviato dall'evento timer al passaggio 3)
- Avvia il servizio
- Setup Timer - Setup in modo che non ci siano sovrapposizioni, solo 1 chiamata di elaborazione può essere effettuata.
- Metodo di elaborazione
- Effettua una chiamata al database per ottenere informazioni che sono un elenco di
Commands
. - Raccoglie una raccolta di
Handlers
. - Esiste un
Parallel.ForEach()
nell'elenco diCommands
. - Immediatamente fa un normale
foreach()
suHandlers
- Effettua una chiamata al database per ottenere informazioni che sono un elenco di
THREADS DI COMANDO
- Comando fa un% normale
foreach()
suHandlers
che passa inCommand
. - Ogni
Handler
esegue codice che può CRUD il database o raggiungere altri servizi.- A causa di
Parallel.ForEach()
sto girando su 1 nuovo thread perCommand
. - Ci potrebbe essere 1000 +
- Poiché ogni
Command
ha piùHandlers
questiHandlers
verrà eseguito sullo stesso thread diCommand
. - Questo serve a prevenire i conflitti di database poiché ogni
Handler
funzionerà con lo stesso insieme di dati. - Si tratta di fare in modo che ogni
Command
aspetti i propri threadHandler
.
- A causa di
WAIT POINTS
- Il servizio attende tutti
Commands
per terminare l'esecuzione prima di eseguire un altro giro di comandi. -
Commands
aspetta tuttiHandlers
fino alla fine. -
Handlers
aspetta che uno finisca prima di passare al successivo.
Performance
- 3000x FOREACH Console.WriteLine () avg. 160ms
- 3000x FORALL Console.WriteLine () avg. 275ms
- 3000x FOREACH DatabaseCallAsync () avg. 1200ms
- 3000x FORALL DatabaseCallAsync () avg. 600ms
Interessante come il foreach normale sia più veloce con solo WriteLine () ma due volte più lento con la chiamata al database. Continuo a preoccuparmi di competere per le risorse con gli altri servizi.
DOMANDE
- Riconosci eventuali problemi immediati con questo design?
- Hai qualche suggerimento che lo renderebbe più efficiente con risorse e velocità?
- Sto notando un utilizzo estremamente elevato della CPU su tutti i core quando si esegue solo
Console.WriteLines()
nel punto di esecuzione effettivo, dovrei limitare i thread?- Ho notato che quando usavo un normale
foreach()
aveva ancora un utilizzo della CPU piuttosto alto ma aveva più punti di riposo, ho ancora bisogno di mettere un contatore lì per vedere quante chiamate sono effettivamente fatte per ciascuna per vedere quale è in realtà l'elaborazione di più, ma in questo momento sono solo preoccupato per l'uso elevato.
- Ho notato che quando usavo un normale