Ответ
Технически — да, но делать этого категорически не рекомендуется для рабочих приложений.
Проблемный пример (антипаттерн):
[HttpPost("start-task")]
public IActionResult StartTask()
{
// ПЛОХО: Приложение ничего не знает об этой задаче.
Task.Run(() =>
{
Thread.Sleep(5000); // Имитация долгой работы
_logger.LogInformation("Task completed");
});
return Ok("Задача запущена");
}
Риски такого подхода:
- Потеря задачи: При рестарте или остановке приложения (деплой, масштабирование) задача будет безвозвратно потеряна.
- Отсутствие отслеживания: Нет возможности узнать статус выполнения, обработать ошибки или отменить задачу.
- Проблемы с DI: Фоновая задача, захватившая Scoped-сервис из контроллера, может использовать его после завершения HTTP-запроса, что приведет к
ObjectDisposedException.
Правильные решения в ASP.NET Core:
-
IHostedService/BackgroundService(для долгоживущих задач):public class TimedBackgroundService : BackgroundService { protected override async Task ExecuteAsync(CancellationToken stoppingToken) { while (!stoppingToken.IsCancellationRequested) { _logger.LogInformation("Worker running at: {time}", DateTimeOffset.Now); await Task.Delay(1000, stoppingToken); // Работа каждую секунду } } } // Регистрация: services.AddHostedService<TimedBackgroundService>(); -
Queued Hosted Service(для фоновых задач по запросу): Создайте безопасную очередь (Channel<T>илиBlockingCollection<T>), куда контроллер будет помещать работу, а фоновая служба — выполнять. -
Специализированные библиотеки: Для сложных сценариев (повторные попытки, планирование, панель мониторинга) используйте Hangfire или Quartz.NET. Они надежно хранят состояние задач и обеспечивают их выполнение.
Вывод: Task.Run в контроллере — это "fire and forget", что небезопасно. Используйте встроенные механизмы фоновых служб или проверенные сторонние решения.