我有服务正在运行,我想检测它是否空闲了 5 分钟。如果是这样,我想在我的 C# 代码中触发方法调用。
有没有办法检测 C# 中 Web api 休息服务的空闲时间? 我在 kestrel 上运行我的服务,但它也需要在托管容器的 docker 中工作。
我在 stackoverflow 和 Google 上都进行了搜索,但我只能找到有关 winform 应用程序的空闲时间。
您可以从 .Net 端实现此目的,如下所示:
为您想要触发的任务创建一个服务。
公共类IdleTimeTrackerService{ 私有只读 ILogger _logger;
public IdleTimeTrackerService(ILogger<IdleTimeTrackerService>logger)
{
_logger = logger;
}
public async Task DoSomethingAsync()
{
await Task.Delay(100);
//在这里调用你的方法 _logger.LogInformation("示例服务做了一些事情。"); }}
创建一个定期托管服务来实现后台服务。
公共类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;
}
}
}
}
}
制作一个重置计时器的中间件(周期性计时器不提供重置计时器的方法,但我们在步骤 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);
}
}
在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();