Asp.net core ASP.NET Core 3.0在应用程序启动时执行逻辑
我有数据库记录,对于每一个记录,我应该在应用程序启动时有重复的作业。我想我可以使用Asp.net core ASP.NET Core 3.0在应用程序启动时执行逻辑,asp.net-core,Asp.net Core,我有数据库记录,对于每一个记录,我应该在应用程序启动时有重复的作业。我想我可以使用IHostedService和定义一个作用域服务来做到这一点,但这是不可能的,因为我的作用域服务的生存期较短IHostedService需要单例服务,这会导致死路一条,因为ApplicationDbContext需要作用域服务 InvalidOperationException:无法使用singleton“Microsoft.Extensions.Hosting.IHostedService”中的作用域服务“Bin
IHostedService
和定义一个作用域服务来做到这一点,但这是不可能的,因为我的作用域服务的生存期较短IHostedService
需要单例服务,这会导致死路一条,因为ApplicationDbContext需要作用域服务
InvalidOperationException:无法使用singleton“Microsoft.Extensions.Hosting.IHostedService”中的作用域服务“Binance.Services.IBotService”
我只需要在应用程序启动时执行该逻辑。在这种情况下,什么是最好的
namespace Binance.Services
{
public class BotHostedService : IHostedService
{
private readonly ILogger _logger;
private readonly IBotService _botService;
private int _numberOfBots;
public BotHostedService(ILogger<BotHostedService> logger, IBotService botService)
{
_logger = logger;
_botService = botService;
}
public async Task StartAsync(CancellationToken cancellationToken)
{
_logger.LogInformation("Bot service is starting.");
var bots = await _botService.GetAllAsync();
_numberOfBots = bots.Count;
for (int i = 0; i < _numberOfBots; i++)
{
Bot bot = bots[i];
_logger.LogDebug($"{bot.Name} is starting. Symbol: {bot.CryptoPair.Description}, Interval: {bot.TimeInterval.Description}");
RecurringJob.AddOrUpdate($"bot{i}", () => DoWork(bot), $"0/5 * * * *", TimeZoneInfo.Local);
}
}
public void DoWork(Bot bot)
{
_logger.LogError($"{bot.Name} is working. Current time: {DateTime.Now.ToLocalTime()}");
}
public Task StopAsync(CancellationToken cancellationToken)
{
_logger.LogInformation("Bot service is stopping.");
for (int i = 0; i < _numberOfBots; i++)
{
RecurringJob.RemoveIfExists($"bot{i}");
}
return Task.CompletedTask;
}
}
}
namespace Binance.Services
{
公共类BotHostedService:IHostedService
{
专用只读ILogger\u记录器;
私有只读IBotService\u botService;
私人智能手机;
公共BotHostedService(ILogger记录器、IBotService botService)
{
_记录器=记录器;
_机器人服务=机器人服务;
}
公共异步任务StartAsync(CancellationToken CancellationToken)
{
_logger.LogInformation(“Bot服务正在启动”);
var bots=await_botService.GetAllAsync();
_numberOfBots=bots.Count;
对于(int i=0;i<\u机器人数量;i++)
{
机器人=机器人[i];
_LogDebug($“{bot.Name}正在启动。符号:{bot.CryptoPair.Description},间隔:{bot.TimeInterval.Description}”);
RecurringJob.AddOrUpdate($“bot{i}”,()=>DoWork(bot),$“0/5****”,TimeZoneInfo.Local);
}
}
公共无效工作(Bot)
{
_logger.LogError($“{bot.Name}正在工作。当前时间:{DateTime.Now.ToLocalTime()}”);
}
公共任务StopAsync(CancellationToken CancellationToken)
{
_logger.LogInformation(“Bot服务正在停止”);
对于(int i=0;i<\u机器人数量;i++)
{
RecurringJob.RemoveIfExists($“bot{i}”);
}
返回Task.CompletedTask;
}
}
}
您可以通过构造函数注入一个IServiceProvider
,然后在必要时创建一个作用域,如下所示:
使用(var scope=this.serviceProvider.CreateScope())
{
IBotService-botService=scope.ServiceProvider.GetRequiredService();
//使用它
}
您可以通过构造函数注入一个IServiceProvider
,然后在必要时创建一个作用域,如下所示:
使用(var scope=this.serviceProvider.CreateScope())
{
IBotService-botService=scope.ServiceProvider.GetRequiredService();
//使用它
}
本节对此进行了说明。答案是在需要时在服务内部创建一个作用域。为此,必须将IServiceProvider添加到服务的依赖项中,例如:
public class BotHostedService : IHostedService
{
//...
private readonly IServiceProvider _services;
public BotHostedService(IServiceProvider services, ILogger<BotHostedService> logger)
{
_logger = logger;
_services=services;
}
public async Task StartAsync(CancellationToken cancellationToken)
{
_logger.LogInformation("Bot service is starting.");
using (var scope = _services.CreateScope())
{
var botService = scope.ServiceProvider
.GetRequiredService<IBotService>();
var bots = await _botService.GetAllAsync();
...
}
}
公共类BotHostedService:IHostedService
{
//...
私人只读阅读器ViceProvider服务;
公共BotHostedService(IServiceProvider服务,ILogger记录器)
{
_记录器=记录器;
_服务=服务;
}
公共异步任务StartAsync(CancellationToken CancellationToken)
{
_logger.LogInformation(“Bot服务正在启动”);
使用(var scope=\u services.CreateScope())
{
var botService=scope.ServiceProvider
.GetRequiredService();
var bots=await_botService.GetAllAsync();
...
}
}
这在的一节中进行了描述。答案是在需要时在服务内部创建一个作用域。为此,必须将IServiceProvider
添加到服务的依赖项中,例如:
public class BotHostedService : IHostedService
{
//...
private readonly IServiceProvider _services;
public BotHostedService(IServiceProvider services, ILogger<BotHostedService> logger)
{
_logger = logger;
_services=services;
}
public async Task StartAsync(CancellationToken cancellationToken)
{
_logger.LogInformation("Bot service is starting.");
using (var scope = _services.CreateScope())
{
var botService = scope.ServiceProvider
.GetRequiredService<IBotService>();
var bots = await _botService.GetAllAsync();
...
}
}
公共类BotHostedService:IHostedService
{
//...
私人只读阅读器ViceProvider服务;
公共BotHostedService(IServiceProvider服务,ILogger记录器)
{
_记录器=记录器;
_服务=服务;
}
公共异步任务StartAsync(CancellationToken CancellationToken)
{
_logger.LogInformation(“Bot服务正在启动”);
使用(var scope=\u services.CreateScope())
{
var botService=scope.ServiceProvider
.GetRequiredService();
var bots=await_botService.GetAllAsync();
...
}
}
谢谢!如果我的服务是singleton,我也可以使用这种方式吗?@不可以。调用服务的生命周期是什么并不重要。如果是singleton,你不需要手动创建作用域,因为托管服务已注册为singleton。你只需通过constructor@mcont如果是这样的话,就会有no需要创建一个作用域。后台服务的行为类似于单例。此外,在应用程序的生命周期内保持昂贵的类(如DbContext
)处于活动状态会导致严重的并发问题谢谢!如果我的服务是单例的,我也可以使用这种方式吗?@不,是的。调用的生命周期是什么并不重要ing服务是。如果它是单例,则不需要手动创建作用域,因为托管服务已注册为单例。您只需通过constructor@mcont如果是这样的话,就不需要创建作用域。后台服务的行为类似于单例。此外,保留一个昂贵的类,如DbContext
在应用程序的生命周期内保持活动状态会导致严重的并发问题谢谢!我接受了另一个答案,因为他更快。事实相反,但没有问题:)谢谢!我接受了另一个答案,因为他更快。事实相反,但没有问题:)