如何创建一个在给定时间段内运行函数的后台服务?使用C#(asp.net core 3.1.1)
我正在尝试每隔指定的时间间隔调用一个函数,因为我使用后台服务,下面是我所做的: 这是警报控制器,我在这里有以下功能:如何创建一个在给定时间段内运行函数的后台服务?使用C#(asp.net core 3.1.1),c#,asp.net-core,background-service,C#,Asp.net Core,Background Service,我正在尝试每隔指定的时间间隔调用一个函数,因为我使用后台服务,下面是我所做的: 这是警报控制器,我在这里有以下功能: public class AlertingController : ControllerBase { private readonly DatabaseContext _context; private readonly IMapper _mapper; public AlertingController(DatabaseContext context,
public class AlertingController : ControllerBase
{
private readonly DatabaseContext _context;
private readonly IMapper _mapper;
public AlertingController(DatabaseContext context, IMapper mapper)
{
_context = context ?? throw new ArgumentNullException(nameof(context));
_mapper = mapper ?? throw new ArgumentNullException(nameof(mapper));
}
public AlertingController()
{
}
//function that adds in the DB
public async Task<AlertingResponse> GetAlertingToDB()
{
AlertingResponse dataGet;
using (var httpClient = new HttpClient())
{
using (var response = await httpClient
.GetAsync(MetricApiLink))
{
string apiResponse = await response.Content.ReadAsStringAsync();
dataGet = JsonConvert.DeserializeObject<AlertingResponse>(apiResponse);
}
}
if (dataGet.data.alerts != null || dataGet.data.alerts.Count > 0)
{
foreach (var alert in dataGet.data.alerts)
{
CreateAlertQuery QueryAlert = new CreateAlertQuery();
QueryAlert.Name = alert.labels.alertname;
QueryAlert.Instance = alert.labels.instance;
QueryAlert.Serverity = alert.labels.severity;
QueryAlert.Summary = alert.annotations.summary;
QueryAlert.State = alert.state;
QueryAlert.ActiveAt = alert.activeAt;
var _Alert = _mapper.Map<AlertingDataModel>(QueryAlert);
_context.Alertings.Add(_Alert);
await _context.SaveChangesAsync();
}
}
return null;
}
}
我还创建了将使用我的服务并在后台运行的类:
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<IScopedAlertingService>();
await scopedProcessingService.DoWork(stoppingToken);
}
}
public override async Task StopAsync(CancellationToken stoppingToken)
{
_logger.LogInformation(
"Consume Scoped Service Hosted Service is stopping.");
await Task.CompletedTask;
}
}
公共类ConsumeScopedService HostedService:BackgroundService
{
专用只读ILogger\u记录器;
公共消费范围服务托管服务(IServiceProvider services,
ILogger(记录器)
{
服务=服务;
_记录器=记录器;
}
公共IServiceProvider服务{get;}
受保护的覆盖异步任务ExecuteAsync(CancellationToken stoppingToken)
{
_logger.login信息(
“使用作用域服务托管服务运行。”);
等待工作(停止工作);
}
专用异步任务DoWork(CancellationToken stoppingToken)
{
_logger.login信息(
“使用作用域服务托管服务正在工作。”);
使用(var scope=Services.CreateScope())
{
var scopedProcessingService=
scope.ServiceProvider
.GetRequiredService();
等待范围处理服务。停止工作(停止工作);
}
}
公共覆盖异步任务StopAsync(CancellationToken stoppingToken)
{
_logger.login信息(
“使用作用域服务承载的服务正在停止。”);
等待任务。完成任务;
}
}
我在Startup类中注入了依赖项,并添加了托管服务:
services.AddHostedService<ConsumeScopedServiceHostedService>();
services.AddScoped<IScopedAlertingService, ScopedAlertingService>();
services.AddHostedService();
services.addScope();
在调用GetAlertingToDB()
函数之前,这些函数一直工作正常,但它不工作
任何帮助都会很好,谢谢大家:)Hangfire Recurreng Job将是您案例的一个选择。你可以在这里查一下。
使用它的好处是:您有一个仪表板来检查何时启动任务以及任务的结果。有几个选项可供选择 请阅读Microsoft文档中的以下链接,其中有几个关于如何在.NET Core和ASP.NET Core中执行此操作的示例: 它被称为工人服务 您基本上实现了两个接口:IHostedService和IDisposable 然后在ConfigureServices方法中的Startup类中注册服务,如下所示:
services.AddHostedService<MyCoolWorkerServiceClass>();
services.AddHostedService();
暂时
最后一个建议。该示例使用System.Threading.Timer。。。但我认为最好使用System.Timers.Timer和AutoReset=false
原因是为了避免服务的重复运行。完成跑步后,再次启动计时器
但这一切都取决于您想要实现什么。我个人会重新安排您的解决方案,这样您的后台服务就不需要创建
控制器了。相反,如果您仍然需要它,控制器应该调用您的ScopedAlertingService
,在那里工作执行一次。您的后台服务可以通过等待Task.Delay()
永远循环
公共类ScopedAlertingService:IScopedAlertingService
{
公共异步任务DoWork(CancellationToken stoppingToken)
{
//将AlertingController.GetAlertingToDB的内容移到此处
}
}
公共类ConsumeScopedService HostedService:BackgroundService
{
私人只读阅读器ViceProvider服务;
公共消费范围服务托管服务(IServiceProvider服务)
{
_服务=服务;
}
受保护的覆盖异步任务ExecuteAsync(CancellationToken stoppingToken)
{
同时(!stoppingToken.IsCancellationRequested)
{
等待任务。延迟(10000,停止待命);
使用(var scope=\u services.CreateScope())
{
var scopedProcessingService=
scope.ServiceProvider
.GetRequiredService();
等待范围处理服务。停止工作(停止工作);
}
}
}
}
正如我在他们的文档中看到的那样,我们可以在API中运行后台服务,我还观看了youtube上的一个教程,其中有人通过修剪vdeios等创建了一个项目。。。使用排队的后台服务,单独运行它们可能是个好主意,但我更喜欢在应用程序启动时运行服务,在应用程序启动时关闭服务shuts@Hasagiii:当然,您可以在proc中并行运行后台服务,但是你不能直接从后台服务打电话给控制器,好吗?谢谢:)改用定时后台任务。我在asp.net core中添加了一个带有此示例的链接。HangFire基于asp.net框架,我使用.net core进行多平台,我知道有很多库,如quartz net等。。但我更喜欢使用托管服务:)我正在使用hangfire for.netcore,它部署在ubuntu服务器上,运行良好。你有没有检查过hangfire页面,它有一句话:“在.NET和.NET核心应用程序中执行后台处理的简单方法”是的,非常感谢很多人,因为现在我已经管理了它的功能,你的想法很好,我将在将来使用它以满足某些需要:DI保留了代码原样,我刚刚将函数移动到DoWork()
方法,现在它工作正常,我将尝试以另一种方式再次执行:)是的@Jonathan,我看到了示例,尝试按照他们说的做,但我无法调用该函数,我想每次我需要映射器和DB上下文时,我都必须对它们进行维护?@Hasagiii是的,但不是创建一个“Sco”
services.AddHostedService<MyCoolWorkerServiceClass>();