Прежде всего, не скрывайте операцию пула потоков в своей службе; пусть вызывающий код решит, запускать операцию в пуле потоков или нет:
Поскольку вы используете внедрение зависимостей, платформа избавляется от вашего DbContext
в конце HTTP-запроса.
Вам необходимо внедрить фабрику области обслуживания в контроллер и запросить службу оттуда:
public class MyController : Controller
{
private readonly IMyService _myService;
private readonly IServiceScopeFactory _scopeFactory;
public MyController(IMyService myService, IServiceScopeFactory scopeFactory)
{
_myService = myService;
_scopeFactory = scopeFactory;
}
public async Task<IActionResult> Create(...)
{
HostingEnvironment.QueueBackgroundWorkItem(SaveInBackground);
return View();
}
private async Task SaveInBackground(CancellationToken ct)
{
using (var scope = scopeFactory.CreateScope())
{
var scopedService = scope.ServiceProvider.GetRequiredService<IMyService>();
await scopedService.CreatePostAsync(...);
}
}
}
HostingEnvironment.QueueBackgroundWorkItem
работает аналогично Task.Run
, за исключением того, что оно гарантирует, что приложение не закрывается, пока не будут выполнены все фоновые рабочие элементы.
Ваша служба должна выглядеть примерно так:
public class MyService : IMyService
{
private readonly MyDbContext _dbContext;
public MyService(MyDbContext dbContext)
{
_dbContext = dbContext;
}
public async Task CreatePostAsync(Post post)
{
_dbContext.Post.Add(post);
await _dbContext.SaveChangesAsync();
}
}
ОБНОВЛЕНИЕ
Для передачи дополнительных параметров в SaveInBackground
:
private async Task SaveInBackground(YourParam param)
Затем вызовите как:
HostingEnvironment.QueueBackgroundWorkItem(cancellationToken => SaveInBackground(yourParam));