Skip to content

Commit a99a739

Browse files
committed
thread-safety fixes & refactoring
1 parent 10e7382 commit a99a739

13 files changed

Lines changed: 47 additions & 54 deletions

File tree

OpenHardwareMonitor/UI/HardwareNode.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ public HardwareNode(IHardware hardware, PersistentSettings settings)
1919
Hardware = hardware;
2020
Image = HardwareTypeImage.Instance.GetImage(hardware.HardwareType);
2121

22+
lock (_typeNodes)
2223
foreach (SensorType sensorType in Enum.GetValues(typeof(SensorType)))
2324
_typeNodes.Add(new TypeNode(sensorType, hardware.Identifier, _settings));
2425

@@ -94,6 +95,7 @@ private void UpdateNode(TypeNode node)
9495

9596
private void SensorRemoved(ISensor sensor)
9697
{
98+
lock (_typeNodes)
9799
foreach (TypeNode typeNode in _typeNodes)
98100
{
99101
if (typeNode.SensorType == sensor.SensorType)
@@ -125,6 +127,7 @@ private void InsertSorted(Node node, ISensor sensor)
125127

126128
private void SensorAdded(ISensor sensor)
127129
{
130+
lock(_typeNodes)
128131
foreach (TypeNode typeNode in _typeNodes)
129132
{
130133
if (typeNode.SensorType == sensor.SensorType)

OpenHardwareMonitor/UI/MainForm.cs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -511,14 +511,15 @@ private void InitializeTheme()
511511
private void InsertSorted(IList<Node> nodes, HardwareNode node)
512512
{
513513
int i = 0;
514-
while (i < nodes.Count && nodes[i] is HardwareNode && ((HardwareNode)nodes[i]).Hardware.HardwareType <= node.Hardware.HardwareType)
514+
while (i < nodes.Count && nodes[i] is HardwareNode hNode && hNode.Hardware.HardwareType <= node.Hardware.HardwareType)
515515
i++;
516-
517516
nodes.Insert(i, node);
518517
}
519518

520519
private void SubHardwareAdded(IHardware hardware, Node node)
521520
{
521+
if (node.Nodes.Any(x => x is HardwareNode hNode && hNode.Hardware.Identifier.ToString() == hardware.Identifier.ToString()))
522+
return;
522523
HardwareNode hardwareNode = new(hardware, _settings);
523524
InsertSorted(node.Nodes, hardwareNode);
524525
foreach (IHardware subHardware in hardware.SubHardware)
@@ -711,7 +712,7 @@ private void TreeView_KeyDown(object sender, KeyEventArgs e)
711712
}
712713
else if (e.KeyCode == Keys.T && e.Control)
713714
{
714-
if (!_systemTray.Add(sensorNode.Sensor))
715+
if (!_systemTray.Add(sensorNode.Sensor, false))
715716
_systemTray.Remove(sensorNode.Sensor);
716717
e.Handled = true;
717718
}

OpenHardwareMonitor/UI/SensorGadget.cs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -332,7 +332,8 @@ private void SensorRemoved(ISensor sensor)
332332

333333
public bool Contains(ISensor sensor)
334334
{
335-
return _sensors.Values.Any(list => list.Contains(sensor));
335+
lock(_sensors)
336+
return _sensors.Values.Any(list => list.Any(x => x.Identifier.ToString() == sensor.Identifier.ToString()));
336337
}
337338

338339
public bool Add(ISensor sensor)
@@ -346,6 +347,8 @@ public bool Add(ISensor sensor)
346347
hardware = hardware.Parent;
347348

348349
// get the sensor list associated with the hardware
350+
lock (_sensors)
351+
{
349352
if (!_sensors.TryGetValue(hardware, out IList<ISensor> list))
350353
{
351354
list = new List<ISensor>();
@@ -358,6 +361,7 @@ public bool Add(ISensor sensor)
358361
i++;
359362

360363
list.Insert(i, sensor);
364+
}
361365

362366
_settings.SetValue(new Identifier(sensor.Identifier, "gadget").ToString(), true);
363367
Resize();
@@ -374,11 +378,11 @@ private void Remove(ISensor sensor, bool deleteConfig)
374378
if (deleteConfig)
375379
_settings.Remove(new Identifier(sensor.Identifier, "gadget").ToString());
376380

381+
lock (_sensors)
377382
foreach (KeyValuePair<IHardware, IList<ISensor>> keyValue in _sensors)
378383
{
379-
if (keyValue.Value.Contains(sensor))
384+
if (keyValue.Value.Remove(sensor))
380385
{
381-
keyValue.Value.Remove(sensor);
382386
if (keyValue.Value.Count == 0)
383387
{
384388
_sensors.Remove(keyValue.Key);
@@ -446,6 +450,7 @@ private void Resize(int width)
446450
{
447451
int y = _topMargin;
448452

453+
lock (_sensors)
449454
foreach (KeyValuePair<IHardware, IList<ISensor>> pair in _sensors)
450455
{
451456
if (_hardwareNames.Value)
@@ -563,6 +568,7 @@ protected override void OnPaint(PaintEventArgs e)
563568
new Rectangle(x, y - 1, w - RightBorder - x, 0));
564569
}
565570

571+
lock (_sensors)
566572
foreach (KeyValuePair<IHardware, IList<ISensor>> pair in _sensors)
567573
{
568574
if (_hardwareNames.Value)

OpenHardwareMonitor/UI/SystemTray.cs

Lines changed: 15 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
using System;
2-
using System.Collections.Generic;
3-
using System.Linq;
2+
using System.Collections.Concurrent;
43
using System.Windows.Forms;
54
using OpenHardwareMonitor.Hardware;
65
using OpenHardwareMonitor.Utilities;
@@ -10,7 +9,7 @@ namespace OpenHardwareMonitor.UI;
109
public class SystemTray : IDisposable
1110
{
1211
private readonly PersistentSettings _settings;
13-
private readonly List<SensorNotifyIcon> _sensorList = new List<SensorNotifyIcon>();
12+
private readonly ConcurrentDictionary<string, SensorNotifyIcon> _sensorList = new();
1413
private bool _mainIconEnabled;
1514
private readonly NotifyIconAdv _mainIcon;
1615

@@ -78,37 +77,35 @@ private void SensorAdded(ISensor sensor)
7877

7978
private void SensorRemoved(ISensor sensor)
8079
{
81-
if (Contains(sensor))
82-
Remove(sensor, false);
80+
Remove(sensor, false);
8381
}
8482

8583
public void Dispose()
8684
{
87-
foreach (SensorNotifyIcon icon in _sensorList)
85+
foreach (SensorNotifyIcon icon in _sensorList.Values)
8886
icon.Dispose();
8987
_mainIcon.Dispose();
9088
}
9189

9290
public void Redraw()
9391
{
94-
SensorNotifyIcon[] sensorsToRedraw;
95-
lock (_sensorList)
96-
{
97-
sensorsToRedraw = _sensorList.ToArray();
98-
}
99-
100-
foreach (SensorNotifyIcon icon in sensorsToRedraw)
92+
foreach (SensorNotifyIcon icon in _sensorList.Values)
10193
icon.Update();
10294
}
10395

104-
public bool Contains(ISensor sensor) => _sensorList.Any(icon => icon.Sensor == sensor);
96+
public bool Contains(ISensor sensor) => _sensorList.ContainsKey(sensor.Identifier.ToString());
10597

106-
public bool Add(ISensor sensor)
98+
public bool Add(ISensor sensor, bool replaceExisting = true)
10799
{
108100
if (Contains(sensor))
109-
return false;
101+
{
102+
if (replaceExisting)
103+
Remove(sensor);
104+
else
105+
return false;
106+
}
110107

111-
_sensorList.Add(new SensorNotifyIcon(this, sensor, _settings));
108+
_sensorList[sensor.Identifier.ToString()] = new SensorNotifyIcon(this, sensor, _settings);
112109
UpdateMainIconVisibility();
113110
_settings.SetValue(new Identifier(sensor.Identifier, "tray").ToString(), true);
114111
return true;
@@ -126,13 +123,8 @@ private void Remove(ISensor sensor, bool deleteConfig)
126123
_settings.Remove(new Identifier(sensor.Identifier, "tray").ToString());
127124
_settings.Remove(new Identifier(sensor.Identifier, "traycolor").ToString());
128125
}
129-
SensorNotifyIcon instance;
130-
lock(_sensorList)
131-
instance = _sensorList.FirstOrDefault(icon => icon.Sensor == sensor);
132-
if (instance != null)
126+
if (_sensorList.TryRemove(sensor.Identifier.ToString(), out SensorNotifyIcon instance))
133127
{
134-
lock (_sensorList)
135-
_sensorList.Remove(instance);
136128
UpdateMainIconVisibility();
137129
instance.Dispose();
138130
}

OpenHardwareMonitorLib/Hardware/Battery/Battery.cs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -110,8 +110,6 @@ public Battery
110110
}
111111
}
112112

113-
public uint BatteryTag => _batteryTag;
114-
115113
public float? ChargeDischargeCurrent { get; private set; }
116114

117115
public float? ChargeDischargeRate { get; private set; }

OpenHardwareMonitorLib/Hardware/Battery/BatteryGroup.cs

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
using System;
22
using System.Collections.Generic;
33
using System.IO;
4-
using System.Linq;
54
using System.Runtime.InteropServices;
65
using System.Text;
76
using OpenHardwareMonitor.Interop;
@@ -101,8 +100,7 @@ public unsafe BatteryGroup(ISettings settings)
101100
ref bqi.BatteryTag,
102101
Marshal.SizeOf(bqi.BatteryTag),
103102
out _,
104-
IntPtr.Zero)
105-
&& _hardware.All(x => x.BatteryTag != bqi.BatteryTag))
103+
IntPtr.Zero))
106104
{
107105
Kernel32.BATTERY_INFORMATION bi = default;
108106
bqi.InformationLevel = Kernel32.BATTERY_QUERY_INFORMATION_LEVEL.BatteryInformation;
@@ -128,10 +126,6 @@ public unsafe BatteryGroup(ISettings settings)
128126
}
129127
}
130128
}
131-
else
132-
{
133-
battery.Close();
134-
}
135129
}
136130
}
137131

OpenHardwareMonitorLib/Hardware/Computer.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ public Computer(ISettings settings)
6868
public event HardwareEventHandler HardwareRemoved;
6969

7070
/// <inheritdoc />
71-
public IList<IHardware> Hardware
71+
public IReadOnlyList<IHardware> Hardware
7272
{
7373
get
7474
{

OpenHardwareMonitorLib/Hardware/Controller/TBalancer/TBalancer.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,12 +90,14 @@ public override HardwareType HardwareType
9090

9191
protected override void ActivateSensor(ISensor sensor)
9292
{
93+
lock (_active)
9394
_deactivating.Remove(sensor);
9495
base.ActivateSensor(sensor);
9596
}
9697

9798
protected override void DeactivateSensor(ISensor sensor)
9899
{
100+
lock (_active)
99101
if (_deactivating.Contains(sensor))
100102
{
101103
_deactivating.Remove(sensor);

OpenHardwareMonitorLib/Hardware/Hardware.cs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ public virtual IHardware Parent
6666
/// <inheritdoc />
6767
public virtual ISensor[] Sensors
6868
{
69-
get { return _active.ToArray(); }
69+
get { lock(_active) return [.. _active]; }
7070
}
7171

7272
/// <inheritdoc />
@@ -96,22 +96,23 @@ public void Accept(IVisitor visitor)
9696
/// <inheritdoc />
9797
public virtual void Traverse(IVisitor visitor)
9898
{
99+
lock (_active)
99100
foreach (ISensor sensor in _active)
100101
sensor.Accept(visitor);
101102
}
102103

103104
/// <inheritdoc />
104105
protected virtual void ActivateSensor(ISensor sensor)
105106
{
106-
if (_active.Add(sensor))
107-
SensorAdded?.Invoke(sensor);
107+
lock (_active) if (!_active.Add(sensor)) return;
108+
SensorAdded?.Invoke(sensor);
108109
}
109110

110111
/// <inheritdoc />
111112
protected virtual void DeactivateSensor(ISensor sensor)
112113
{
113-
if (_active.Remove(sensor))
114-
SensorRemoved?.Invoke(sensor);
114+
lock (_active) if (!_active.Remove(sensor)) return;
115+
SensorRemoved?.Invoke(sensor);
115116
}
116117

117118
/// <inheritdoc />

OpenHardwareMonitorLib/Hardware/IComputer.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ public interface IComputer : IElement
2828
/// <para>Can be updated by <see cref="IVisitor" />.</para>
2929
/// </summary>
3030
/// <returns>List of all enabled devices.</returns>
31-
IList<IHardware> Hardware { get; }
31+
IReadOnlyList<IHardware> Hardware { get; }
3232

3333
/// <summary>
3434
/// Gets or sets a value indicating whether collecting information about <see cref="HardwareType.Battery" /> devices should be enabled and updated.

0 commit comments

Comments
 (0)