2015-05-22 4 views
8

Sto bagnando i piedi con il costrutto asincrono/atteso di .NET 4.5. Sto lavorando a una soluzione RESTful Web API. Sto cercando di capire cosa fare con l'operazione legata alla CPU - 1) chiamarlo in modo sincrono dal thread corrente, oppure 2) usare Task.Run()?Confusione sulla chiamata sincrona dei metodi associati alla CPU da un metodo asincrono

Usiamo l'esempio da questo page:

async Task<int> AccessTheWebAsync() 
{ 
    // You need to add a reference to System.Net.Http to declare client. 
    HttpClient client = new HttpClient(); 

    // GetStringAsync returns a Task<string>. That means that when you await the 
    // task you'll get a string (urlContents). 
    Task<string> getStringTask = client.GetStringAsync("http://msdn.microsoft.com"); 

    // You can do work here that doesn't rely on the string from GetStringAsync. 
    DoCPUBoundWork(); 

    // The await operator suspends AccessTheWebAsync. 
    // - AccessTheWebAsync can't continue until getStringTask is complete. 
    // - Meanwhile, control returns to the caller of AccessTheWebAsync. 
    // - Control resumes here when getStringTask is complete. 
    // - The await operator then retrieves the string result from getStringTask. 
    string urlContents = await getStringTask; 

    // The return statement specifies an integer result. 
    // Any methods that are awaiting AccessTheWebAsync retrieve the length value. 
    return urlContents.Length; 
} 

Qui, supponiamo DoCPUBoundWork() è strettamente CPU-bound e non comporta alcun IO di alcun tipo.

È la procedura migliore per chiamarlo dal thread corrente come mostrato?

O è meglio avere il seguente?

Ho letto su alcuni messaggi di Mr. Cleary e sto ottenendo alcuni suggerimenti misti. In questo post, suggerisce che è meglio chiamare la roba legata alla CPU in modo sincrono per evitare l'inutile sovraccarico di async/await/Task.Run(). Tuttavia, in questo post, suggerisce di utilizzare Task.Run() per le operazioni associate alla CPU senza menzionare casi di eccezione. Sono sicuro che mi manca qualcosa di ovvio. Sperando di avere qualche chiarimento su questo.

+0

Per quanto tempo viene eseguito in genere DoIndependentWork? –

+0

Supponiamo che ci vuole abbastanza tempo per causare problemi sotto carico elevato ... – Zoomzoom

risposta

6

È la procedura migliore per chiamarlo dal thread corrente come mostrato?

Se il thread corrente è gratuito mentre il funzionamento asincrono è in corso, perché utilizzare un thread diverso? Cosa renderebbe il thread migliore di quello che stai già utilizzando?

Mi viene in mente la domanda relativa a ciò che DoIndependentWork sta effettivamente facendo. Se è vitale che completi prima che la richiesta HTTP termini, la invocherò in modo sincrono. Se il lavoro non è vitale da completare prima del completamento della richiesta HTTP, allora cercherò una soluzione completamente diversa. L'utilizzo di Task.Run è pericoloso in ASP.NET.

Ricordare che le continue in ASP.NET vengono eseguite su thread di thread thread arbitrari.

+0

Quindi ... quando ha senso scaricarlo su un altro thread usando Task.Run()? (Sono confuso perché Stephen Cleary suggerisce di usare Task.Run() per le risorse legate alla CPU nel suo blog) – Zoomzoom

+0

e riguardo i thread * legati * a ui in wpf? sparare un compito extra per evitare il blocco del gui sarebbe fattibile ... –

+2

@Andreas Hai ragione, nel caso questo fosse WPF consiglierei in modo diverso. Ma questo è ASP.NET, che è diverso. –