Fixes applied (14 of 15 findings — see note on R5)
Concurrency crashes - H1 HardwareMonitorService.RebuildTree now builds the tree under _updateLock, so it can't enumerate a hardware's _active HashSet while the update loop mutates it. - A1 AppSettings now guards every dictionary read/write (and snapshots in Save) with a lock — safe under concurrent access from the parallel discovery threads. - R2 Plumbed that same lock (HardwareMonitorService.SensorReadLock) into RemoteWebServer and wrapped the Prometheus sensor.Values enumeration with it. - L1 Computer — refactored Add into AddCore, which performs the cancellation/enabled re-check and the _groups insertion atomically under _lock. A deferred task can no longer add (and leak) a group after Close() drained the list; if it loses the race it closes the group instead. - M1 UpdateTimer_Tick now bails before/after the await when _isShuttingDown is set in MainWindow_Closed, so an in-flight tick won't touch the disposed view-model/Computer. Broken behavior - T1 Tray callback now decodes NOTIFYICON_VERSION_4 correctly (message = LOWORD(lParam), icon id = HIWORD(lParam)) — right-click menu and double-click work again. - M2 A transient update exception no longer calls _timer.Stop(); the loop keeps running. - H2 Newly discovered (deferred) storage devices get the current ForceDriveWakeup setting applied in HardwareChanged. - V2 Sensor items carry a parent reference; toggling IsVisible recomputes the parent group's visibility, so no empty group headers. (Strengthened the existing test that had skipped this assertion.) - H3 Tree-rebuild coalescing now uses a dirty flag with a re-check, so a change arriving during a rebuild isn't lost. - R4 Web routing matches endpoints exactly on the query-stripped path (Url.AbsolutePath), so static assets like metrics.html aren't hijacked. - L8 IntelCpu.Update skips the bus/core-clock math while TimeStampCounterFrequency is still 0 (deferred-TSC window), so clocks keep their prior value instead of reporting 0 MHz. - V1 Existing plot series keep their assigned color; only an explicit user pen color updates them (no per-tick color shifting). - M3 Runtime errors write to a dedicated runtime.log (once), instead of overwriting the shared startup.log. - T2 CreateSensorIcon returns IntPtr.Zero on DIB failure instead of the shared main-icon handle (which callers DestroyIcon). I also set _isOpen = false in HardwareMonitorService.Dispose so the rebuild guard actually holds during shutdown (the latent after-close-rebuild issue adjacent to H3
This commit is contained in:
@@ -18,6 +18,7 @@ namespace LibreHardwareMonitor.Windows.WinUI.ViewModels;
|
||||
public sealed class SensorTreeItemViewModel : ViewModelBase
|
||||
{
|
||||
private readonly AppSettings? _settings;
|
||||
private SensorTreeItemViewModel? _parent;
|
||||
private string? _expandedSettingName;
|
||||
private bool _isExpanded = true;
|
||||
private bool _isVisible = true;
|
||||
@@ -68,6 +69,10 @@ public sealed class SensorTreeItemViewModel : ViewModelBase
|
||||
_settings?.SetValue(new Identifier(Sensor.Identifier, "hidden").ToString(), !value);
|
||||
|
||||
UpdateVisibilityState();
|
||||
|
||||
// A SensorType group's visibility depends on whether any child is visible, so recompute the parent too;
|
||||
// otherwise hiding the last visible sensor leaves an empty group header (and the reverse on show).
|
||||
_parent?.UpdateVisibilityState();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -320,7 +325,11 @@ public sealed class SensorTreeItemViewModel : ViewModelBase
|
||||
};
|
||||
|
||||
foreach (ISensor sensor in sensors)
|
||||
item.Children.Add(FromSensor(sensor, settings));
|
||||
{
|
||||
SensorTreeItemViewModel child = FromSensor(sensor, settings);
|
||||
child._parent = item;
|
||||
item.Children.Add(child);
|
||||
}
|
||||
|
||||
item.UpdateVisibilityState();
|
||||
return item;
|
||||
|
||||
Reference in New Issue
Block a user