// File: Services/Scanners/ThreadScanner.cs using System.Diagnostics; using WebmrAPI.Models; using WebmrAPI.Utils; namespace WebmrAPI.Services.Scanners { public class ThreadScanner : AbstractCpuScanner { override public ScanTarget Target { get => ScanTarget.Threads; } internal int PID { get; private set; } override internal async Task ScanAsync(Dictionary data) { return await Task.Run(() => { try { using (var process = Process.GetProcessById(PID)) foreach (ProcessThread thread in process.Threads) { ProcessThreadInfo info; if (GetFromCacheOrNew(thread.Id, out info)) { info.CpuUsage = CalcCpuUsage(info.ProcessorTime, Container.Elapsed.TotalMilliseconds); } else { info.ID = thread.Id; info.CpuUsage = 0; } info.BasePriority = thread.BasePriority; info.CurrentPriority = thread.CurrentPriority; info.TotalProcessorTime = thread.TotalProcessorTime; data.Add(info.ID, info); } return true; } catch (System.ComponentModel.Win32Exception ex) when (ex.NativeErrorCode == 5) { Provider.Logger.LogWarning($"Access denied to process {PID} for thread scanning. Error: {ex.Message}"); } catch (InvalidOperationException ex) { Provider.Logger.LogWarning($"Process {PID} might have exited during thread enumeration. Error: {ex.Message}"); } catch (Exception ex) { Provider.Logger.LogError($"An unexpected error occurred while scanning threads for PID {PID}. Error: {ex.Message}"); } return false; }); } public ThreadScanner(IScanProvider scanner, LazyConcurrentContainer container, int pid) : base(scanner, container) { PID = pid; } } }