Files
SpdUp/Services/MonitoringService.cs
T
Phil-icyou 19ba425e79 Initial commit: SpdUp Windows Gaming Booster v1.0.0
- .NET 8 WPF app with full MVVM architecture
- One-click boost: CPU, RAM, GPU, network, services, timer resolution
- Real-time system monitor (LibreHardwareMonitor)
- Auto game detection (30+ games)
- RAM optimizer with kernel-level cleanup
- Network optimizer (TCP registry tweaks)
- Service manager, process manager, shader cache cleaner
- Desktop widget overlay
- Debug log viewer
- Custom dark gaming theme with trans pride colors
- 84 unit tests (xUnit)
- Inno Setup installer script
- Landing page website
2026-03-08 17:34:45 +01:00

158 lines
5.1 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using System.Diagnostics;
using System.Runtime.InteropServices;
using LibreHardwareMonitor.Hardware;
using SpdUp.Core;
using SpdUp.Models;
namespace SpdUp.Services;
/// <summary>
/// Live system monitoring using performance counters + LibreHardwareMonitor.
/// Designed for low overhead one shared timer drives all consumers.
/// </summary>
public sealed class MonitoringService : IDisposable
{
private readonly Timer _timer;
private readonly Computer _computer;
private readonly PerformanceCounter _cpuCounter;
private readonly NetworkService _networkService = new();
private readonly string _pingTarget;
private SystemMetrics _latest = new();
private bool _disposed;
public event Action<SystemMetrics>? MetricsUpdated;
public SystemMetrics Latest => _latest;
public MonitoringService(string pingTarget = "8.8.8.8")
{
_pingTarget = pingTarget;
// CPU % counter
_cpuCounter = new PerformanceCounter("Processor", "% Processor Time", "_Total", readOnly: true);
_cpuCounter.NextValue(); // prime the counter
// LibreHardwareMonitor for temps + GPU
_computer = new Computer
{
IsCpuEnabled = true,
IsGpuEnabled = true,
IsMemoryEnabled = true,
};
try
{
_computer.Open();
}
catch (Exception ex)
{
Logger.Warn($"LibreHardwareMonitor init warning: {ex.Message}");
}
_timer = new Timer(Tick, null, Timeout.Infinite, Timeout.Infinite);
}
public void Start(int intervalMs = 1000)
{
_timer.Change(0, intervalMs);
Logger.Info($"Monitoring started ({intervalMs} ms interval).");
}
public void Stop()
{
_timer.Change(Timeout.Infinite, Timeout.Infinite);
Logger.Info("Monitoring stopped.");
}
public void SetInterval(int intervalMs)
{
_timer.Change(0, intervalMs);
}
private async void Tick(object? state)
{
if (_disposed) return;
try
{
float cpuUsage = _cpuCounter.NextValue();
// Memory
var mem = new NativeMethods.MEMORYSTATUSEX { dwLength = (uint)Marshal.SizeOf<NativeMethods.MEMORYSTATUSEX>() };
NativeMethods.GlobalMemoryStatusEx(ref mem);
float ramTotal = mem.ullTotalPhys / 1048576f;
float ramUsed = ramTotal - (mem.ullAvailPhys / 1048576f);
// Hardware sensors
float cpuTemp = 0, gpuUsage = 0, gpuTemp = 0;
try
{
foreach (var hw in _computer.Hardware)
{
hw.Update();
foreach (var sensor in hw.Sensors)
{
if (hw.HardwareType == HardwareType.Cpu &&
sensor.SensorType == SensorType.Temperature &&
sensor.Name.Contains("Package", StringComparison.OrdinalIgnoreCase))
{
cpuTemp = sensor.Value ?? 0;
}
if ((hw.HardwareType == HardwareType.GpuNvidia || hw.HardwareType == HardwareType.GpuAmd || hw.HardwareType == HardwareType.GpuIntel))
{
if (sensor.SensorType == SensorType.Load && sensor.Name.Contains("Core", StringComparison.OrdinalIgnoreCase))
gpuUsage = sensor.Value ?? 0;
if (sensor.SensorType == SensorType.Temperature && sensor.Name.Contains("Core", StringComparison.OrdinalIgnoreCase))
gpuTemp = sensor.Value ?? 0;
}
}
foreach (var sub in hw.SubHardware)
{
sub.Update();
foreach (var sensor in sub.Sensors)
{
if (sensor.SensorType == SensorType.Temperature &&
sensor.Name.Contains("Package", StringComparison.OrdinalIgnoreCase))
cpuTemp = sensor.Value ?? cpuTemp;
}
}
}
}
catch { /* sensor read failure continue with zeros */ }
// Ping
long pingMs = await NetworkService.PingAsync(_pingTarget, 1500);
_latest = new SystemMetrics
{
CpuUsage = cpuUsage,
RamUsageMB = ramUsed,
RamTotalMB = ramTotal,
GpuUsage = gpuUsage,
CpuTemperature = cpuTemp,
GpuTemperature = gpuTemp,
NetworkPingMs = pingMs,
Fps = 0, // FPS hook not implemented without injection
};
MetricsUpdated?.Invoke(_latest);
}
catch (Exception ex)
{
Logger.Error("Monitoring tick error", ex);
}
}
public void Dispose()
{
if (_disposed) return;
_disposed = true;
_timer.Dispose();
_cpuCounter.Dispose();
try { _computer.Close(); } catch { }
}
}