using System; using System.Threading; using System.Threading.Tasks; using LavishVMAPI; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; using MRBot.PassiveTasks; using StackExchange.Profiling; namespace MRBot.Services; internal sealed class PassiveTaskManager : BackgroundService { private const uint PulseRate = 10; private readonly ILogger _logger; private readonly IPassiveTaskList _passiveTaskList; private readonly MiniProfiler _profiler; private DateTime _lastLogTime = DateTime.MinValue; private uint _pulseCount; public PassiveTaskManager(IPassiveTaskList passiveTaskList, ILogger logger, MiniProfiler profiler) { _passiveTaskList = passiveTaskList; _logger = logger; _profiler = profiler; } private bool ShouldPulse { get { if (_pulseCount >= PulseRate) { _pulseCount = 0; return true; } _pulseCount++; return false; } } public override Task StartAsync(CancellationToken cancellationToken) { _logger.LogInformation("Starting passive task manager"); return base.StartAsync(cancellationToken); } public override Task StopAsync(CancellationToken cancellationToken) { _logger.LogInformation("Stopping passive task manager"); return base.StopAsync(cancellationToken); } private Task ServiceLoopAsync(CancellationToken stoppingToken) { while (!stoppingToken.IsCancellationRequested) { if (!ShouldPulse) continue; // using (_profiler.Step("PassiveTaskManager.ServiceLoopAsync")) { foreach (var task in _passiveTaskList) { if (stoppingToken.IsCancellationRequested) return Task.FromCanceled(stoppingToken); _logger.LogInformation($"Pulsing task {task.Type}"); // using (_profiler.Step($"FrameLock.{task.Type}")) using (new FrameLock(true)) { task.Execute(); } } } Thread.Sleep(500); } return Task.CompletedTask; } protected override Task ExecuteAsync(CancellationToken stoppingToken) { return Task.Factory.StartNew(async () => { await ServiceLoopAsync(stoppingToken); }, stoppingToken, TaskCreationOptions.LongRunning, TaskScheduler.Default); } public override void Dispose() { _logger.LogInformation("Disposing passive task manager"); base.Dispose(); } }