Mam metodę w aplikacji ASP.NET, której wykonanie zajmuje dużo czasu. Wywołanie tej metody może wystąpić do 3 razy podczas jednego żądania użytkownika, w zależności od stanu pamięci podręcznej i parametrów podanych przez użytkownika. Każde połączenie trwa około 1-2 sekund. Sama metoda jest synchronicznym wywołaniem usługi i nie ma możliwości nadpisania implementacji.
Więc synchroniczne wywołanie usługi wygląda mniej więcej tak:
public OutputModel Calculate(InputModel input)
{
// do some stuff
return Service.LongRunningCall(input);
}
A użycie metody to (zauważ, że wywołanie metody może się zdarzyć więcej niż raz):
private void MakeRequest()
{
// a lot of other stuff: preparing requests, sending/processing other requests, etc.
var myOutput = Calculate(myInput);
// stuff again
}
Próbowałem zmienić implementację z mojej strony, aby zapewnić jednoczesną pracę tej metody i oto do czego doszedłem do tej pory.
public async Task<OutputModel> CalculateAsync(InputModel input)
{
return await Task.Run(() =>
{
return Calculate(input);
});
}
Użycie (część kodu „do innych rzeczy” działa jednocześnie z wywołaniem usługi):
private async Task MakeRequest()
{
// do some stuff
var task = CalculateAsync(myInput);
// do other stuff
var myOutput = await task;
// some more stuff
}
Moje pytanie jest następujące. Czy używam właściwego podejścia, aby przyspieszyć wykonywanie w aplikacji ASP.NET, czy też wykonuję niepotrzebne zadanie, próbując uruchomić kod synchroniczny asynchronicznie? Czy ktoś może wyjaśnić, dlaczego drugie podejście nie jest opcją w ASP.NET (jeśli tak naprawdę nie jest)? Ponadto, jeśli takie podejście jest możliwe, czy muszę wywoływać taką metodę asynchronicznie, jeśli jest to jedyne wywołanie, jakie możemy w tej chwili wykonać (mam taki przypadek, gdy nie ma innych rzeczy do zrobienia w oczekiwaniu na zakończenie)?
Większość artykułów w sieci na ten temat dotyczy użycia async-await
podejścia z kodem, który już dostarcza awaitable
metod, ale to nie mój przypadek. Tutajto fajny artykuł opisujący mój przypadek, który nie opisuje sytuacji połączeń równoległych, rezygnując z opcji zawijania wywołania synchronizacji, ale moim zdaniem moja sytuacja jest właśnie do tego okazją.
Z góry dziękuję za pomoc i wskazówki.
Task.Run
, zawartość jest uruchamiana w innym wątku, który jest pobierany z puli wątków. Wtedy nie ma potrzeby zawijania wywołań blokujących (takich jak moje wywołanie usługi) wRun
s, ponieważ każdy z nich będzie zawsze zużywał jeden wątek, który zostanie zablokowany podczas wykonywania metody. W takiej sytuacji jedyną korzyścią, jakaasync-await
mi pozostała, jest wykonywanie kilku czynności na raz. Proszę popraw mnie jeżeli się mylę.