Ho letto tutte le domande correlate in SO, ma un po 'confuso sull'approccio migliore per il mio scenario in cui vengono attivate più chiamate al servizio web.Task.StartNew() vs Parallel.ForEach: scenario Richieste Web multiple
Ho un servizio di aggregazione che prende un input, lo analizza e lo traduce in più richieste web, effettua le chiamate di richiesta web (non correlate, quindi potrebbero essere attivate in parallelo) e consolida la risposta che viene inviata al chiamante. Il codice seguente viene utilizzato in questo momento -
list.ForEach((object obj) =>
{
tasks.Add(Task.Factory.StartNew((object state) =>
{
this.ProcessRequest(obj);
}, obj, CancellationToken.None, TaskCreationOptions.AttachedToParent, TaskScheduler.Default));
});
await Task.WhenAll(tasks);
il await Task.WhenAll(tasks)
viene da Scott Hanselman di post in cui si dice che
"Una soluzione migliore dal punto di vista di scalabilità, dice Stefano, è quello di approfittare di I/O asincrono Quando si chiama attraverso la rete , non c'è alcuna ragione (diversa dalla convenienza) per bloccare i thread mentre si attende che la risposta torni "
Il codice esistente sembra consumare troppi thread e il tempo processore aumenta fino al 100% sul carico di produzione e questo mi fa riflettere.
L'altra alternativa è utilizzare Parallel.ForEach che utilizza un partizionatore ma anche "blocca" la chiamata, che va bene per il mio scenario.
Considerando che questo è tutto lavoro "Async IO" e non "CPU bound", e le richieste web non sono lunghe (ritorno in max 3 secondi), tendo a credere che il codice esistente sia abbastanza buono. Ma questo fornirebbe un throughput migliore di Parallel.ForEach? Parallel.ForEach probabilmente utilizza il numero "minimo" di Attività a causa del partizionamento e quindi dell'uso ottimale dei thread (?). Ho testato Parallel.ForEach con alcuni test locali e non sembra essere migliore.
L'obiettivo è ridurre il tempo di CPU e aumentare il throughput e quindi una migliore scalabilità. Esiste un approccio migliore per la gestione delle richieste Web in parallelo?
Apprezzare qualsiasi input, grazie.
EDIT: metodo ProcessRequest illustrato nel codice di esempio utilizza infatti HttpClient e dei suoi metodi asincroni al fuoco richieste (PostAsync, GetAsync, PutAsync).
Se 'ProcessRequest' utilizza metodi asincroni, perché sono voi calli lo trovi all'interno di 'Task.Factory.StartNew'? Potresti semplicemente aggiungere l'attività che ritorna alla tua lista. Se stai bloccando al suo interno, non importa che tu usi metodi asincroni in parti di esso. L'ultima chiamata di blocco annulla qualsiasi beneficio –
"diverso dalla convenienza", beh, questa è una buona ragione. – usr