Ho un metodo nell'applicazione ASP.NET, che richiede molto tempo per essere completato. Una chiamata a questo metodo potrebbe verificarsi fino a 3 volte durante una richiesta utente, a seconda dello stato della cache e dei parametri forniti dall'utente. Ogni chiamata richiede circa 1-2 secondi per essere completata. Il metodo stesso è una chiamata sincrona al servizio e non è possibile sovrascrivere l'implementazione.
Quindi la chiamata sincrona al servizio è simile alla seguente:
public OutputModel Calculate(InputModel input)
{
// do some stuff
return Service.LongRunningCall(input);
}
E l'utilizzo del metodo è (nota, quella chiamata di metodo può accadere più di una volta):
private void MakeRequest()
{
// a lot of other stuff: preparing requests, sending/processing other requests, etc.
var myOutput = Calculate(myInput);
// stuff again
}
Ho provato a cambiare l'implementazione da parte mia per fornire il lavoro simultaneo di questo metodo, ed ecco cosa sono arrivato finora.
public async Task<OutputModel> CalculateAsync(InputModel input)
{
return await Task.Run(() =>
{
return Calculate(input);
});
}
Utilizzo (parte del codice "fai altre cose" viene eseguita contemporaneamente alla chiamata al servizio):
private async Task MakeRequest()
{
// do some stuff
var task = CalculateAsync(myInput);
// do other stuff
var myOutput = await task;
// some more stuff
}
La mia domanda è la seguente. Utilizzo l'approccio corretto per accelerare l'esecuzione nell'applicazione ASP.NET o sto eseguendo un lavoro non necessario cercando di eseguire codice sincrono in modo asincrono? Qualcuno può spiegare perché il secondo approccio non è un'opzione in ASP.NET (se non lo è davvero)? Inoltre, se tale approccio è applicabile, devo chiamare tale metodo in modo asincrono se è l'unica chiamata che potremmo eseguire al momento (ho questo caso, quando non c'è altra cosa da fare in attesa del completamento)?
La maggior parte degli articoli in rete su questo argomento tratta dell'utilizzo async-await
dell'approccio con il codice, che già fornisce awaitable
metodi, ma non è il mio caso. Quiè il bell'articolo che descrive il mio caso, che non descrive la situazione delle chiamate parallele, rifiutando l'opzione di wrap sync call, ma secondo me la mia situazione è proprio l'occasione per farlo.
Grazie in anticipo per aiuto e suggerimenti.
Task.Run
, il contenuto viene eseguito in un altro thread, che viene preso dal pool di thread. Quindi non è affatto necessario avvolgere le chiamate di blocco (come la mia chiamata al servizio) inRun
s, perché consumeranno sempre un thread ciascuno, che verrà bloccato durante l'esecuzione del metodo. In una situazione del genere l'unico vantaggio che rimaneasync-await
nel mio caso è eseguire più azioni alla volta. Per favore correggimi se sbaglio.