如何在 C# Web api Rest 应用程序中检测服务是否空闲?

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

我有服务正在运行,我想检测它是否空闲了 5 分钟。如果是这样,我想在我的 C# 代码中触发方法调用。

有没有办法检测 C# 中 Web api 休息服务的空闲时间? 我在 kestrel 上运行我的服务,但它也需要在托管容器的 docker 中工作。

我在 stackoverflow 和 Google 上都进行了搜索,但我只能找到有关 winform 应用程序的空闲时间。

c# asp.net .net docker asp.net-web-api
1个回答
0
投票

您可以从 .Net 端实现此目的,如下所示:

  1. 为您想要触发的任务创建一个服务。

    公共类IdleTimeTrackerService{ 私有只读 ILogger _logger;

    public IdleTimeTrackerService(ILogger<IdleTimeTrackerService>logger)
    {
        _logger = logger;
    }
    
    public async Task DoSomethingAsync()
    {
        await Task.Delay(100);
    

    //在这里调用你的方法 _logger.LogInformation("示例服务做了一些事情。"); }}

  2. 创建一个定期托管服务来实现后台服务。

    公共类PeriodicHostedService:BackgroundService { 公共只读 TimeSpan _period = TimeSpan.FromSeconds(3); 私有只读 ILogger _logger; 私有只读 IServiceScopeFactory _factory; 私有 int _executionCount = 0; 私人 CancellationTokenSource _cts;

    public void ResetTimer()
    {
        // Cancel the current timer
        _cts.Cancel();
    
        // Create a new timer
        _cts = new CancellationTokenSource();
    }
    
    public PeriodicHostedService(
        ILogger<PeriodicHostedService> logger,
        IServiceScopeFactory factory)
    {
        _cts = new CancellationTokenSource();
        _logger = logger;
        _factory = factory;
    }
    
    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        while (!stoppingToken.IsCancellationRequested)
        {
            using PeriodicTimer timer = new PeriodicTimer(_period);
            while (await timer.WaitForNextTickAsync(stoppingToken))
            {
                try
                {
                    await Task.Delay(_period, _cts.Token);
                    await using AsyncServiceScope asyncScope = _factory.CreateAsyncScope();
                    IdleTimeTrackerService idleTimeTrackerService = asyncScope.ServiceProvider.GetRequiredService<IdleTimeTrackerService>();
                    await idleTimeTrackerService.DoSomethingAsync();
                    _executionCount++;
                    _logger.LogInformation(
                        $"Executed PeriodicHostedService - Count: {_executionCount}");
                }
                catch (Exception ex)
                {
                    _logger.LogInformation(
                        $"Execution of PeriodicHostedService skipped with exception message {ex.Message}. Good luck next round!");
                    continue;
                }
            }
        }
    }
    

    }

  3. 制作一个重置计时器的中间件(周期性计时器不提供重置计时器的方法,但我们在步骤 2 中通过在请求取消时跳过服务调用来解决此问题),我们提供了一个名为 ResetTimer 的方法,该方法将从该中间件调用:

    公共类ChangeStateMiddleware { 私有只读RequestDelegate _next; 私有只读PeriodicHostedService _service;

    public ChangeStateMiddleware(RequestDelegate next, PeriodicHostedService service)
    {
        _next = next;
        _service = service;
    }
    
    public async Task Invoke(HttpContext context)
    {
    
        _service.ResetTimer();
        Console.WriteLine($"Service timer reset successfully!");
        await _next(context);   
    }
    

    }

  4. 在program.cs中注册服务并使用中间件,如下所示:

    // 将服务添加到容器中。

    builder.Services.AddControllers();

    builder.Services.AddScoped(); builder.Services.AddSingleton(); builder.Services.AddHostedService( 提供者 => 提供者.GetRequiredService());

    var app = builder.Build();

    // 配置 HTTP 请求管道。

    app.UseHttpsRedirection();

    app.UseMiddleware();

    app.UseAuthorization();

    app.MapControllers();

    app.Run();

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