2014-06-23 11 views
5

Possiedo un'azione del controller MVC che deve eseguire diverse richieste Web. Quindi, in un tentativo di liberare questo thread per gestire altre richieste in arrivo web ho scritto qualcosa di simile: (NOTA: questa è una semplificazione del codice reale)Does Task.Factory.StartNew aiuta o danneggia in ASP.Net MVC?

public async Task<ViewResult> Index() 
{ 
    MyObj o = await Task.Factory.StartNew<MyObj>(() => 
    { 
     WebClient c = new WebClient(); 
     var res1 = c.DownloadString("..."); 
     var res2 = c.DownloadString("..."); //Not shown but res1 required for this call. 
     return new MyObj(res1, res2); 
    } 
    return View(o); 
} 

La mia domanda è ho ho fatto le cose meglio o peggio girando una nuova discussione per fare questo lavoro. La mia intenzione è quella di liberare questo thread .Net per gestire altre richieste in entrata mentre vengono fatte le richieste di rete. Ma dopo averlo guardato sembra che sto ancora facendo un blocco di thread .Net, solo forse uno diverso dal pool di thread invece dell'originale, quindi non sto davvero meglio. Quindi il mio sospetto è corretto e il codice sopra riportato peggiora le cose?

Il vantaggio di Task.Factory.StartNew() se ha funzionato ... è che semplifica il lavoro all'interno da dover fare tutto asincrono. La mia domanda è: fa in questo modo in effetti liberare un thread per gestire le richieste web in arrivo o sta ancora legando lo stesso numero di thread dal pool di thread?

risposta

4

Sì, stai solo bloccando una discussione diversa ora.

Se ciò fosse positivo, MVC avvolgerebbe automaticamente tutti i metodi di azione in una nuova attività.

Per sbloccare i thread è necessario un IO asincrono da qualche parte sotto le copertine. Il BCL di solito fornisce questo. Se dice "asincrono" sulla scatola, di solito è un IO asincrono.

Detto questo, poche app Web hanno il problema di rimanere senza thread. Il pool di thread inizia tonnellate di thread, se necessario. Pochissime applicazioni web hanno un throughput limitato dal numero di thread disponibili. Hai davvero bisogno di elaborare centinaia di richieste simultanee? I tuoi servizi di back-end possono gestire questo carico? Se a una di queste domande viene risposto "no" non è necessario asincrare.

+0

Grazie, ha senso che avresti bisogno di blocchi di basso livello per la creazione di veri metodi asincroni che non userebbero un thread .net. – user3766657

1

Non è necessario il blocco di fabbrica. È possibile semplificare il vostro esempio a:

public async Task<ViewResult> Index() 
{ 
    WebClient client = new WebClient(); 
    var result1 = await client.DownloadStringAsync("..."); 
    var result2 = await client.DownloadStringAsync("..."); 

    /* whatever you're doing with result1 & result2 */  

    return View(); 
} 
+0

Il mio esempio è semplificato perché la cosa reale è inutilmente complessa per dimostrare la domanda. Il vantaggio di Task.Factory.StartNew() se ha funzionato ... è che semplifica il lavoro all'interno da dover fare tutto asincrono. La mia domanda però è se farlo in quel modo non libera in effetti un thread per gestire le richieste web o se sta ancora legando lo stesso numero di thread dal pool di thread. – user3766657

2

Il codice che hai fatto non è davvero ottimale, dal momento che entrambe le operazioni di blocco lungo l'un l'altro:

var result1 = c.DownloadString("..."); 

verrà eseguito prima e una volta fatto, si corre

var result2 = c.DownloadString("..."); 

L'aggiunta di un thread aggiuntivo in cui viene eseguito non migliorerà le prestazioni, né libererà eventuali richieste aperte.

+0

Non è mostrato, ma devono essere eseguiti in serie perché la seconda chiamata Web dipende dai risultati del 1 °. Ma questa non è la domanda che sto ponendo. – user3766657

+0

Se dipendono l'uno dall'altro, non è necessario creare un thread aggiuntivo. Questo non ti aiuterà in alcun modo allora. –

+0

Penso che ti sbagli. L'obiettivo non è la parallelizzazione, sta aumentando il numero di richieste concorrenti che puoi gestire. – user3766657

Problemi correlati