问题描述
我从主页调用这样的服务:
_ = _importUserService.AddManyUserAsync(ValidatedUsers);
我希望 Page() 返回并让用户/UI 继续前进,同时服务在后台添加许多使用 UserManager 的用户。问题是,一旦 Page() 返回并且请求完成,IdentityDbContext 就会关闭并且 UserManager 不再起作用。请求完成后,如何让 UserManager 继续工作?
服务使用标准依赖注入:
private readonly UserManager<ApplicationUser> _userManager;
public ImportUserService(UserManager<ApplicationUser> userManager)
{
_userManager = userManager;
}
如果我使用 await 而不是丢弃并强制服务在页面加载之前完成,则效果很好;但是,如果用户需要等待 2 分钟才能在页面加载之前导入数千个用户,这将是糟糕的用户体验。不依赖于请求的生命周期的服务?
我的想法是创建一个 UserManager 的新实例,而不是依赖于依赖注入的实例,但到目前为止我一直无法让它工作。不确定语法是什么,也找不到在 .net core 3.1 中实际工作的示例
如何在请求后保持 IdentityDbContext 处于活动状态,以便服务可以使用 UserManager 完成其任务? (.Net Core 3.1)
解决方法
来自文档
这让我可以运行后台服务,该服务可以调用使用 UserManager 的服务
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
})
.ConfigureServices(services =>
{
services.AddHostedService<ConsumeScopedServiceHostedService>();
});
}
public class ConsumeScopedServiceHostedService : BackgroundService
{
private readonly ILogger<ConsumeScopedServiceHostedService> _logger;
public ConsumeScopedServiceHostedService(IServiceProvider services,ILogger<ConsumeScopedServiceHostedService> logger)
{
Services = services;
_logger = logger;
}
public IServiceProvider Services { get; }
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
_logger.LogInformation(
"Consume Scoped Service Hosted Service running.");
await DoWork(stoppingToken);
}
private async Task DoWork(CancellationToken stoppingToken)
{
_logger.LogInformation(
"Consume Scoped Service Hosted Service is working.");
using (var scope = Services.CreateScope())
{
var scopedProcessingService =
scope.ServiceProvider
.GetRequiredService<IScopedProcessingService>();
await scopedProcessingService.DoWork(stoppingToken);
}
}
public override async Task StopAsync(CancellationToken stoppingToken)
{
_logger.LogInformation(
"Consume Scoped Service Hosted Service is stopping.");
await base.StopAsync(stoppingToken);
}
}
并且工作在 IScopedProcessingService > DoWork(stoppingToken) 中完成 这意味着 ScopedProcessingService 可以访问与使用我的问题中显示的依赖项注入的典型 Web 服务相同的服务。