У мене є метод у програмі ASP.NET, який займає досить багато часу для його завершення. Виклик цього методу може відбуватися до 3 разів під час одного запиту користувача, залежно від стану кешу та параметрів, які надає користувач. Кожен дзвінок займає близько 1-2 секунд. Сам метод - це синхронний виклик служби, і немає можливості замінити реалізацію.
Отже, синхронний дзвінок до служби виглядає приблизно так:
public OutputModel Calculate(InputModel input)
{
// do some stuff
return Service.LongRunningCall(input);
}
І використання методу є (зауважте, що виклик методу може траплятися більше одного разу):
private void MakeRequest()
{
// a lot of other stuff: preparing requests, sending/processing other requests, etc.
var myOutput = Calculate(myInput);
// stuff again
}
Я намагався змінити реалізацію зі свого боку, щоб забезпечити одночасну роботу цього методу, і ось до чого я прийшов до цього часу.
public async Task<OutputModel> CalculateAsync(InputModel input)
{
return await Task.Run(() =>
{
return Calculate(input);
});
}
Використання (частина коду "робити інші речі" виконується одночасно із викликом до служби):
private async Task MakeRequest()
{
// do some stuff
var task = CalculateAsync(myInput);
// do other stuff
var myOutput = await task;
// some more stuff
}
Моє запитання таке. Чи використовую я правильний підхід для прискорення виконання в програмі ASP.NET чи я виконую непотрібну роботу, намагаючись запустити синхронний код асинхронно? Хто-небудь може пояснити, чому другий підхід не є варіантом в ASP.NET (якщо він насправді не є)? Крім того, якщо такий підхід застосовний, чи потрібно мені викликати такий метод асинхронно, якщо це єдиний виклик, який ми можемо виконати на даний момент (у мене такий випадок, коли жодних інших речей не потрібно робити, поки чекаємо завершення)?
Більшість статей у мережі на цю тему охоплює використання async-await
підходу з кодом, який вже надає awaitable
методи, але це не мій випадок. Осьце приємна стаття, що описує мій випадок, яка не описує ситуацію паралельних викликів, відмовляючись від можливості обгортання виклику синхронізації, але, на мій погляд, моя ситуація - саме привід це зробити.
Заздалегідь дякую за допомогу та поради.
Task.Run
, вміст запускається в іншому потоці, який береться з пулу потоків. Тоді взагалі немає необхідності обертати блокуючі виклики (наприклад, мій виклик до служби) вRun
s, оскільки вони завжди будуть споживати по одному потоку, який буде заблокований під час виконання методу. У такій ситуації єдиною перевагою, яка залишиласяasync-await
в моєму випадку, є виконання одночасно декількох дій. Будь ласка, виправте мене, якщо я помиляюся.