我如何创建一个BackGround服务,该服务在给定的时间段内运行一个函数?使用C#(asp.net核心3.1.1)

问题描述 投票:1回答:3

我正在尝试在每个指定的时间间隔内调用函数,为此,我使用后台服务,这是我所做的:这是我具有功能的警报控制器:

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;
    }
}

我已经用HTTPGET请求测试了该方法,它工作正常,将警报添加到我的数据库中:

enter image description here

我创建了一个受监视的服务,在其中我调用了函数GetAlertingToDB()

    internal interface IScopedAlertingService
    {
        Task DoWork(CancellationToken stoppingToken);
    }
    public class ScopedAlertingService : IScopedAlertingService
    {
        private int executionCount = 0;
        private readonly ILogger _logger;

    public ScopedAlertingService(ILogger<ScopedAlertingService> logger)
    {
        _logger = logger;
    }

    public async Task DoWork(CancellationToken stoppingToken)
    {
        AlertingController _AlertingToDB = new AlertingController();
        while (!stoppingToken.IsCancellationRequested)
        {
            executionCount++;

            _logger.LogInformation(
                "Scoped Processing Service is working. Count: {Count}", executionCount);

            await _AlertingToDB.GetAlertingToDB();

            await Task.Delay(10000, stoppingToken);
        }
    }
}

我还创建了将使用我的服务并在BackGround中运行的Class:

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;
    }
}

我将依赖项注入了启动类并添加了托管服务:

        services.AddHostedService<ConsumeScopedServiceHostedService>();
        services.AddScoped<IScopedAlertingService, ScopedAlertingService>();

在调用GetAlertingToDB()函数之前,这些函数正常工作,并且不起作用。

任何帮助都会很棒,谢谢大家:)

c# asp.net-core background-service
3个回答
0
投票

有几种选择的方法。

请阅读Microsoft文档中的以下链接,其中包含有关如何在.NET Core和ASP.NET Core中执行此操作的几个示例:

Worker Service In NET Core

称为工人服务。

您基本上实现了两个接口:IHostedService,IDisposable

然后您像这样在ConfigureServices方法中的Startup类中注册服务:

services.AddHostedService<MyCoolWorkerServiceClass>();

对于Complete Example

最后一个建议。该示例使用System.Threading.Timer ...,但我认为最好将System.Timers.Timer与AutoReset = false一起使用。

原因是为了避免服务运行重叠。运行完成后,您可以重新启动计时器。

但是这又取决于您要实现的目标。


0
投票

我个人将重新安排您的解决方案,以便您的后台服务不需要创建Controller。相反,如果您仍然需要控制器,则应调用您的ScopedAlertingService,在此执行一次工作。您的后台服务可以通过await Task.Delay()永远循环下去。

    public class ScopedAlertingService : IScopedAlertingService
    {
        public async Task DoWork(CancellationToken stoppingToken)
        {
            // move contents of your AlertingController.GetAlertingToDB here
        }
    }

    public class ConsumeScopedServiceHostedService : BackgroundService
    {
        private readonly IServiceProvider _services;
        public ConsumeScopedServiceHostedService(IServiceProvider services)
        {
            _services = services;
        }
        protected override async Task ExecuteAsync(CancellationToken stoppingToken)
        {
            while (!stoppingToken.IsCancellationRequested)
            {
                await Task.Delay(10000, stoppingToken);

                using (var scope = _services.CreateScope())
                {
                    var scopedProcessingService =
                        scope.ServiceProvider
                            .GetRequiredService<IScopedAlertingService>();

                    await scopedProcessingService.DoWork(stoppingToken);
                }
            }
        }
    }

-1
投票

Hangfire RecurringJob将是您的选择。您可以在此处https://docs.hangfire.io/en/latest/background-methods/performing-recurrent-tasks.html进行检查。使用它的好处是:您可以使用仪表板来检查何时触发任务以及任务的结果。

© www.soinside.com 2019 - 2024. All rights reserved.