Ответ 1
Важно различать два разных типа concurrency. Асинхронный concurrency - это когда вы выполняете несколько асинхронных операций в полете (и поскольку каждая операция асинхронна, ни один из них фактически не использует поток). Параллельный concurrency - это когда у вас есть несколько потоков, каждый из которых выполняет отдельную операцию.
Первое, что нужно сделать, это переоценить это предположение:
Сам метод является синхронным вызовом службы, и нет возможности переопределить реализацию.
Если ваш "сервис" - это веб-служба или что-то еще, что связано с I/O-привязкой, лучшим решением будет написать для него асинхронный API.
Я приступлю к предположению, что ваш "сервис" - это операция с привязкой к процессору, которая должна выполняться на том же компьютере, что и веб-сервер.
Если это случай, то следующая оценка - другое предположение:
Мне нужно, чтобы запрос выполнялся быстрее.
Вы абсолютно уверены, что вам нужно? Есть ли какие-либо интерфейсные изменения, которые вы можете сделать вместо этого - например, запустите запрос и разрешите пользователю выполнять другую работу во время обработки?
Я приступлю к предположению, что да, вам действительно нужно ускорить выполнение индивидуального запроса.
В этом случае вам потребуется выполнить параллельный код на вашем веб-сервере. Это наиболее определенно не рекомендуется вообще, потому что параллельный код будет использовать потоки, которые ASP.NET может потребовать для обработки других запросов, а также путем удаления/добавления потоков он выкинет эвристику threadpool ASP.NET. Таким образом, это решение влияет на весь ваш сервер.
Когда вы используете параллельный код на ASP.NET, вы принимаете решение действительно ограничить масштабируемость своего веб-приложения. Вы также можете увидеть значительное количество оттока нити, особенно если ваши запросы все равно. Я рекомендую использовать только параллельный код на ASP.NET, если вы знаете, что количество одновременных пользователей будет довольно низким (т.е. Не общедоступным сервером).
Итак, если вы доберетесь так далеко, и вы уверены, что хотите выполнить параллельную обработку на ASP.NET, у вас есть несколько вариантов.
Один из самых простых способов - использовать Task.Run
, очень похожий на ваш существующий код. Однако я не рекомендую применять метод CalculateAsync
, так как это означает, что обработка является асинхронной (а это не так). Вместо этого используйте Task.Run
в точке вызова:
private async Task MakeRequest()
{
// do some stuff
var task = Task.Run(() => Calculate(myInput));
// do other stuff
var myOutput = await task;
// some more stuff
}
В качестве альтернативы, если он хорошо работает с вашим кодом, вы можете использовать тип Parallel
, т.е. Parallel.For
, Parallel.ForEach
или Parallel.Invoke
. Преимущество кода Parallel
заключается в том, что поток запроса используется как один из параллельных потоков, а затем возобновляет выполнение в контексте потока (там меньше переключения контекста, чем пример async
):
private void MakeRequest()
{
Parallel.Invoke(() => Calculate(myInput1),
() => Calculate(myInput2),
() => Calculate(myInput3));
}
Я не рекомендую использовать Parallel LINQ (PLINQ) на ASP.NET вообще.