У меня есть этот сценарий, в котором у меня есть WebApi и конечная точка, которая при запуске выполняет большую работу (около 2-5 минут). Это конечная точка POST с побочными эффектами, и я хотел бы ограничить выполнение, чтобы, если 2 запроса были отправлены в эту конечную точку (не должно происходить, но лучше перестраховаться), один из них должен был ждать, чтобы избежать гонки условия.
Сначала я попытался использовать простую статическую блокировку внутри контроллера следующим образом:
lock (_lockObj)
{
var results = await _service.LongRunningWithSideEffects();
return Ok(results);
}
это, конечно, невозможно из-за await
внутри оператора lock
.
Другое решение, которое я рассматривал, заключалось в использовании реализации SemaphoreSlim
следующим образом:
await semaphore.WaitAsync();
try
{
var results = await _service.LongRunningWithSideEffects();
return Ok(results);
}
finally
{
semaphore.Release();
}
Однако, согласно MSDN:
Класс SemaphoreSlim представляет собой легкий и быстрый семафор, который можно использовать для ожидания внутри одного процесса, когда ожидается, что время ожидания будет очень коротким.
Так как в этом сценарии время ожидания может достигать 5 минут, что мне использовать для контроля параллелизма?
РЕДАКТИРОВАТЬ (в ответ на plog17):
Я понимаю, что передача этой задачи службе может быть оптимальным способом, однако я не обязательно хочу ставить в очередь что-то в фоновом режиме, которое все еще выполняется после выполнения запроса. Запрос включает в себя другие запросы и интеграции, которые занимают некоторое время, но я все же хотел бы, чтобы пользователь дождался завершения этого запроса и получил ответ в любом случае. Ожидается, что этот запрос будет запускаться только один раз в день в определенное время заданием cron. Тем не менее, есть также возможность запустить его вручную разработчиком (в основном, если что-то пойдет не так с заданием), и я хотел бы убедиться, что API не столкнется с проблемами параллелизма, если разработчик, например. дважды отправляет запрос случайно и т. д.