diff --git a/RGB.NET.Devices.Asus/AsusDeviceProvider.cs b/RGB.NET.Devices.Asus/AsusDeviceProvider.cs index 1558f6d..805db68 100644 --- a/RGB.NET.Devices.Asus/AsusDeviceProvider.cs +++ b/RGB.NET.Devices.Asus/AsusDeviceProvider.cs @@ -16,11 +16,21 @@ public sealed class AsusDeviceProvider : AbstractRGBDeviceProvider { #region Properties & Fields + // ReSharper disable once InconsistentNaming + private static readonly object _lock = new(); + private static AsusDeviceProvider? _instance; /// /// Gets the singleton instance. /// - public static AsusDeviceProvider Instance => _instance ?? new AsusDeviceProvider(); + public static AsusDeviceProvider Instance + { + get + { + lock (_lock) + return _instance ?? new AsusDeviceProvider(); + } + } private IAuraSdk2? _sdk; private IAuraSyncDeviceCollection? _devices; //HACK DarthAffe 05.04.2021: Due to some researches this might fix the access violation in the asus-sdk @@ -35,8 +45,11 @@ public sealed class AsusDeviceProvider : AbstractRGBDeviceProvider /// Thrown if this constructor is called even if there is already an instance of this class. public AsusDeviceProvider() { - if (_instance != null) throw new InvalidOperationException($"There can be only one instance of type {nameof(AsusDeviceProvider)}"); - _instance = this; + lock (_lock) + { + if (_instance != null) throw new InvalidOperationException($"There can be only one instance of type {nameof(AsusDeviceProvider)}"); + _instance = this; + } } #endregion @@ -82,14 +95,17 @@ public sealed class AsusDeviceProvider : AbstractRGBDeviceProvider /// protected override void Dispose(bool disposing) { - base.Dispose(disposing); + lock (_lock) + { + base.Dispose(disposing); - try { _sdk?.ReleaseControl(0); } - catch { /* at least we tried */ } + try { _sdk?.ReleaseControl(0); } + catch { /* at least we tried */ } - _devices = null; - _sdk = null; - _instance = null; + _devices = null; + _sdk = null; + _instance = null; + } } #endregion diff --git a/RGB.NET.Devices.CoolerMaster/CoolerMasterDeviceProvider.cs b/RGB.NET.Devices.CoolerMaster/CoolerMasterDeviceProvider.cs index be075df..8678e1a 100644 --- a/RGB.NET.Devices.CoolerMaster/CoolerMasterDeviceProvider.cs +++ b/RGB.NET.Devices.CoolerMaster/CoolerMasterDeviceProvider.cs @@ -17,11 +17,21 @@ public sealed class CoolerMasterDeviceProvider : AbstractRGBDeviceProvider { #region Properties & Fields + // ReSharper disable once InconsistentNaming + private static readonly object _lock = new(); + private static CoolerMasterDeviceProvider? _instance; /// /// Gets the singleton instance. /// - public static CoolerMasterDeviceProvider Instance => _instance ?? new CoolerMasterDeviceProvider(); + public static CoolerMasterDeviceProvider Instance + { + get + { + lock (_lock) + return _instance ?? new CoolerMasterDeviceProvider(); + } + } /// /// Gets a modifiable list of paths used to find the native SDK-dlls for x86 applications. @@ -45,8 +55,11 @@ public sealed class CoolerMasterDeviceProvider : AbstractRGBDeviceProvider /// Thrown if this constructor is called even if there is already an instance of this class. public CoolerMasterDeviceProvider() { - if (_instance != null) throw new InvalidOperationException($"There can be only one instance of type {nameof(CoolerMasterDeviceProvider)}"); - _instance = this; + lock (_lock) + { + if (_instance != null) throw new InvalidOperationException($"There can be only one instance of type {nameof(CoolerMasterDeviceProvider)}"); + _instance = this; + } } #endregion @@ -96,12 +109,15 @@ public sealed class CoolerMasterDeviceProvider : AbstractRGBDeviceProvider /// protected override void Dispose(bool disposing) { - base.Dispose(disposing); + lock (_lock) + { + base.Dispose(disposing); - try { _CoolerMasterSDK.Reload(); } - catch { /* Unlucky.. */ } + try { _CoolerMasterSDK.Reload(); } + catch { /* Unlucky.. */ } - _instance = null; + _instance = null; + } } #endregion diff --git a/RGB.NET.Devices.Corsair/CorsairDeviceProvider.cs b/RGB.NET.Devices.Corsair/CorsairDeviceProvider.cs index 88f4509..89f4684 100644 --- a/RGB.NET.Devices.Corsair/CorsairDeviceProvider.cs +++ b/RGB.NET.Devices.Corsair/CorsairDeviceProvider.cs @@ -17,11 +17,21 @@ public sealed class CorsairDeviceProvider : AbstractRGBDeviceProvider { #region Properties & Fields + // ReSharper disable once InconsistentNaming + private static readonly object _lock = new(); + private static CorsairDeviceProvider? _instance; /// /// Gets the singleton instance. /// - public static CorsairDeviceProvider Instance => _instance ?? new CorsairDeviceProvider(); + public static CorsairDeviceProvider Instance + { + get + { + lock (_lock) + return _instance ?? new CorsairDeviceProvider(); + } + } /// /// Gets a modifiable list of paths used to find the native SDK-dlls for x86 applications. @@ -80,8 +90,11 @@ public sealed class CorsairDeviceProvider : AbstractRGBDeviceProvider /// Thrown if this constructor is called even if there is already an instance of this class. public CorsairDeviceProvider() { - if (_instance != null) throw new InvalidOperationException($"There can be only one instance of type {nameof(CorsairDeviceProvider)}"); - _instance = this; + lock (_lock) + { + if (_instance != null) throw new InvalidOperationException($"There can be only one instance of type {nameof(CorsairDeviceProvider)}"); + _instance = this; + } } #endregion @@ -302,12 +315,18 @@ public sealed class CorsairDeviceProvider : AbstractRGBDeviceProvider /// protected override void Dispose(bool disposing) { - base.Dispose(disposing); + lock (_lock) + { + base.Dispose(disposing); - try { _CUESDK.CorsairDisconnect(); } catch { /* at least we tried */ } - try { _CUESDK.UnloadCUESDK(); } catch { /* at least we tried */ } + try { _CUESDK.CorsairDisconnect(); } + catch { /* at least we tried */ } - _instance = null; + try { _CUESDK.UnloadCUESDK(); } + catch { /* at least we tried */ } + + _instance = null; + } } #endregion diff --git a/RGB.NET.Devices.DMX/DMXDeviceProvider.cs b/RGB.NET.Devices.DMX/DMXDeviceProvider.cs index 0baad66..d5f2456 100644 --- a/RGB.NET.Devices.DMX/DMXDeviceProvider.cs +++ b/RGB.NET.Devices.DMX/DMXDeviceProvider.cs @@ -16,11 +16,21 @@ public sealed class DMXDeviceProvider : AbstractRGBDeviceProvider { #region Properties & Fields + // ReSharper disable once InconsistentNaming + private static readonly object _lock = new(); + private static DMXDeviceProvider? _instance; /// /// Gets the singleton instance. /// - public static DMXDeviceProvider Instance => _instance ?? new DMXDeviceProvider(); + public static DMXDeviceProvider Instance + { + get + { + lock (_lock) + return _instance ?? new DMXDeviceProvider(); + } + } /// /// Gets a list of all defined device-definitions. @@ -37,8 +47,11 @@ public sealed class DMXDeviceProvider : AbstractRGBDeviceProvider /// Thrown if this constructor is called even if there is already an instance of this class. public DMXDeviceProvider() { - if (_instance != null) throw new InvalidOperationException($"There can be only one instance of type {nameof(DMXDeviceProvider)}"); - _instance = this; + lock (_lock) + { + if (_instance != null) throw new InvalidOperationException($"There can be only one instance of type {nameof(DMXDeviceProvider)}"); + _instance = this; + } } #endregion @@ -89,9 +102,12 @@ public sealed class DMXDeviceProvider : AbstractRGBDeviceProvider /// protected override void Dispose(bool disposing) { - base.Dispose(disposing); + lock (_lock) + { + base.Dispose(disposing); - _instance = null; + _instance = null; + } } #endregion diff --git a/RGB.NET.Devices.Debug/DebugDeviceProvider.cs b/RGB.NET.Devices.Debug/DebugDeviceProvider.cs index f37e4e9..836c6db 100644 --- a/RGB.NET.Devices.Debug/DebugDeviceProvider.cs +++ b/RGB.NET.Devices.Debug/DebugDeviceProvider.cs @@ -16,11 +16,21 @@ public sealed class DebugDeviceProvider : AbstractRGBDeviceProvider { #region Properties & Fields + // ReSharper disable once InconsistentNaming + private static readonly object _lock = new(); + private static DebugDeviceProvider? _instance; /// /// Gets the singleton instance. /// - public static DebugDeviceProvider Instance => _instance ?? new DebugDeviceProvider(); + public static DebugDeviceProvider Instance + { + get + { + lock (_lock) + return _instance ?? new DebugDeviceProvider(); + } + } private List<(IDeviceLayout layout, Action>? updateLedsAction)> _fakeDeviceDefinitions = new(); @@ -34,8 +44,11 @@ public sealed class DebugDeviceProvider : AbstractRGBDeviceProvider /// Thrown if this constructor is called even if there is already an instance of this class. public DebugDeviceProvider() { - if (_instance != null) throw new InvalidOperationException($"There can be only one instance of type {nameof(DebugDeviceProvider)}"); - _instance = this; + lock (_lock) + { + if (_instance != null) throw new InvalidOperationException($"There can be only one instance of type {nameof(DebugDeviceProvider)}"); + _instance = this; + } } #endregion @@ -68,11 +81,14 @@ public sealed class DebugDeviceProvider : AbstractRGBDeviceProvider /// protected override void Dispose(bool disposing) { - base.Dispose(disposing); + lock (_lock) + { + base.Dispose(disposing); - _fakeDeviceDefinitions.Clear(); + _fakeDeviceDefinitions.Clear(); - _instance = null; + _instance = null; + } } #endregion diff --git a/RGB.NET.Devices.Logitech/LogitechDeviceProvider.cs b/RGB.NET.Devices.Logitech/LogitechDeviceProvider.cs index f6a8862..4a12b39 100644 --- a/RGB.NET.Devices.Logitech/LogitechDeviceProvider.cs +++ b/RGB.NET.Devices.Logitech/LogitechDeviceProvider.cs @@ -20,11 +20,21 @@ public class LogitechDeviceProvider : AbstractRGBDeviceProvider { #region Properties & Fields + // ReSharper disable once InconsistentNaming + private static readonly object _lock = new(); + private static LogitechDeviceProvider? _instance; /// /// Gets the singleton instance. /// - public static LogitechDeviceProvider Instance => _instance ?? new LogitechDeviceProvider(); + public static LogitechDeviceProvider Instance + { + get + { + lock (_lock) + return _instance ?? new LogitechDeviceProvider(); + } + } /// /// Gets a modifiable list of paths used to find the native SDK-dlls for x86 applications. @@ -112,7 +122,7 @@ public class LogitechDeviceProvider : AbstractRGBDeviceProvider { 0x0A78, RGBDeviceType.Speaker, "G560", LedMappings.ZoneSpeaker, (LogitechDeviceType.Speaker, 4, 0) }, }; - + /// /// Gets the HID-definitions for wireless per-zone-devices. /// @@ -164,8 +174,12 @@ public class LogitechDeviceProvider : AbstractRGBDeviceProvider /// Thrown if this constructor is called even if there is already an instance of this class. public LogitechDeviceProvider() { - if (_instance != null) throw new InvalidOperationException($"There can be only one instance of type {nameof(LogitechDeviceProvider)}"); - _instance = this; + lock (_lock) + { + if (_instance != null) + throw new InvalidOperationException($"There can be only one instance of type {nameof(LogitechDeviceProvider)}"); + _instance = this; + } } #endregion @@ -256,15 +270,18 @@ public class LogitechDeviceProvider : AbstractRGBDeviceProvider /// protected override void Dispose(bool disposing) { - base.Dispose(disposing); + lock (_lock) + { + base.Dispose(disposing); - try { _LogitechGSDK.LogiLedRestoreLighting(); } - catch { /* at least we tried */ } + try { _LogitechGSDK.LogiLedRestoreLighting(); } + catch { /* at least we tried */ } - try { _LogitechGSDK.UnloadLogitechGSDK(); } - catch { /* at least we tried */ } + try { _LogitechGSDK.UnloadLogitechGSDK(); } + catch { /* at least we tried */ } - _instance = null; + _instance = null; + } } #endregion diff --git a/RGB.NET.Devices.Msi/MsiDeviceProvider.cs b/RGB.NET.Devices.Msi/MsiDeviceProvider.cs index c45a2df..1a305cc 100644 --- a/RGB.NET.Devices.Msi/MsiDeviceProvider.cs +++ b/RGB.NET.Devices.Msi/MsiDeviceProvider.cs @@ -17,11 +17,21 @@ public class MsiDeviceProvider : AbstractRGBDeviceProvider { #region Properties & Fields + // ReSharper disable once InconsistentNaming + private static readonly object _lock = new(); + private static MsiDeviceProvider? _instance; /// /// Gets the singleton instance. /// - public static MsiDeviceProvider Instance => _instance ?? new MsiDeviceProvider(); + public static MsiDeviceProvider Instance + { + get + { + lock (_lock) + return _instance ?? new MsiDeviceProvider(); + } + } /// /// Gets a modifiable list of paths used to find the native SDK-dlls for x86 applications. @@ -45,8 +55,11 @@ public class MsiDeviceProvider : AbstractRGBDeviceProvider /// Thrown if this constructor is called even if there is already an instance of this class. public MsiDeviceProvider() { - if (_instance != null) throw new InvalidOperationException($"There can be only one instance of type {nameof(MsiDeviceProvider)}"); - _instance = this; + lock (_lock) + { + if (_instance != null) throw new InvalidOperationException($"There can be only one instance of type {nameof(MsiDeviceProvider)}"); + _instance = this; + } } #endregion @@ -100,12 +113,15 @@ public class MsiDeviceProvider : AbstractRGBDeviceProvider /// protected override void Dispose(bool disposing) { - base.Dispose(disposing); + lock (_lock) + { + base.Dispose(disposing); - try { _MsiSDK.UnloadMsiSDK(); } - catch { /* at least we tried */ } - - _instance = null; + try { _MsiSDK.UnloadMsiSDK(); } + catch { /* at least we tried */ } + + _instance = null; + } } #endregion diff --git a/RGB.NET.Devices.Novation/NovationDeviceProvider.cs b/RGB.NET.Devices.Novation/NovationDeviceProvider.cs index 9c9555b..9a86f6f 100644 --- a/RGB.NET.Devices.Novation/NovationDeviceProvider.cs +++ b/RGB.NET.Devices.Novation/NovationDeviceProvider.cs @@ -17,11 +17,21 @@ public sealed class NovationDeviceProvider : AbstractRGBDeviceProvider { #region Properties & Fields + // ReSharper disable once InconsistentNaming + private static readonly object _lock = new(); + private static NovationDeviceProvider? _instance; /// /// Gets the singleton instance. /// - public static NovationDeviceProvider Instance => _instance ?? new NovationDeviceProvider(); + public static NovationDeviceProvider Instance + { + get + { + lock (_lock) + return _instance ?? new NovationDeviceProvider(); + } + } #endregion @@ -33,8 +43,11 @@ public sealed class NovationDeviceProvider : AbstractRGBDeviceProvider /// Thrown if this constructor is called even if there is already an instance of this class. private NovationDeviceProvider() { - if (_instance != null) throw new InvalidOperationException($"There can be only one instance of type {nameof(NovationDeviceProvider)}"); - _instance = this; + lock (_lock) + { + if (_instance != null) throw new InvalidOperationException($"There can be only one instance of type {nameof(NovationDeviceProvider)}"); + _instance = this; + } } #endregion @@ -70,9 +83,12 @@ public sealed class NovationDeviceProvider : AbstractRGBDeviceProvider /// protected override void Dispose(bool disposing) { - base.Dispose(disposing); + lock (_lock) + { + base.Dispose(disposing); - _instance = null; + _instance = null; + } } #endregion diff --git a/RGB.NET.Devices.OpenRGB/OpenRGBDeviceProvider.cs b/RGB.NET.Devices.OpenRGB/OpenRGBDeviceProvider.cs index 50647a1..4ad82cc 100644 --- a/RGB.NET.Devices.OpenRGB/OpenRGBDeviceProvider.cs +++ b/RGB.NET.Devices.OpenRGB/OpenRGBDeviceProvider.cs @@ -14,6 +14,9 @@ public sealed class OpenRGBDeviceProvider : AbstractRGBDeviceProvider { #region Properties & Fields + // ReSharper disable once InconsistentNaming + private static readonly object _lock = new(); + private readonly List _clients = new(); private static OpenRGBDeviceProvider? _instance; @@ -21,7 +24,14 @@ public sealed class OpenRGBDeviceProvider : AbstractRGBDeviceProvider /// /// Gets the singleton instance. /// - public static OpenRGBDeviceProvider Instance => _instance ?? new OpenRGBDeviceProvider(); + public static OpenRGBDeviceProvider Instance + { + get + { + lock (_lock) + return _instance ?? new OpenRGBDeviceProvider(); + } + } /// /// Gets a list of all defined device-definitions. @@ -48,8 +58,11 @@ public sealed class OpenRGBDeviceProvider : AbstractRGBDeviceProvider /// Thrown if this constructor is called even if there is already an instance of this class. public OpenRGBDeviceProvider() { - if (_instance != null) throw new InvalidOperationException($"There can be only one instance of type {nameof(OpenRGBDeviceProvider)}"); - _instance = this; + lock (_lock) + { + if (_instance != null) throw new InvalidOperationException($"There can be only one instance of type {nameof(OpenRGBDeviceProvider)}"); + _instance = this; + } } #endregion @@ -151,18 +164,21 @@ public sealed class OpenRGBDeviceProvider : AbstractRGBDeviceProvider /// protected override void Dispose(bool disposing) { - base.Dispose(disposing); - - foreach (OpenRgbClient client in _clients) + lock (_lock) { - try { client.Dispose(); } - catch { /* at least we tried */ } + base.Dispose(disposing); + + foreach (OpenRgbClient client in _clients) + { + try { client.Dispose(); } + catch { /* at least we tried */ } + } + + _clients.Clear(); + DeviceDefinitions.Clear(); + + _instance = null; } - - _clients.Clear(); - DeviceDefinitions.Clear(); - - _instance = null; } #endregion diff --git a/RGB.NET.Devices.PicoPi/PicoPiDeviceProvider.cs b/RGB.NET.Devices.PicoPi/PicoPiDeviceProvider.cs index debdc39..c799460 100644 --- a/RGB.NET.Devices.PicoPi/PicoPiDeviceProvider.cs +++ b/RGB.NET.Devices.PicoPi/PicoPiDeviceProvider.cs @@ -25,11 +25,21 @@ public sealed class PicoPiDeviceProvider : AbstractRGBDeviceProvider #region Properties & Fields + // ReSharper disable once InconsistentNaming + private static readonly object _lock = new(); + private static PicoPiDeviceProvider? _instance; /// /// Gets the singleton instance. /// - public static PicoPiDeviceProvider Instance => _instance ?? new PicoPiDeviceProvider(); + public static PicoPiDeviceProvider Instance + { + get + { + lock (_lock) + return _instance ?? new PicoPiDeviceProvider(); + } + } /// /// Gets the HID-definitions for PicoPi-devices. @@ -57,8 +67,11 @@ public sealed class PicoPiDeviceProvider : AbstractRGBDeviceProvider /// Thrown if this constructor is called even if there is already an instance of this class. public PicoPiDeviceProvider() { - if (_instance != null) throw new InvalidOperationException($"There can be only one instance of type {nameof(PicoPiDeviceProvider)}"); - _instance = this; + lock (_lock) + { + if (_instance != null) throw new InvalidOperationException($"There can be only one instance of type {nameof(PicoPiDeviceProvider)}"); + _instance = this; + } } #endregion @@ -129,9 +142,12 @@ public sealed class PicoPiDeviceProvider : AbstractRGBDeviceProvider /// protected override void Dispose(bool disposing) { - base.Dispose(disposing); + lock (_lock) + { + base.Dispose(disposing); - _instance = null; + _instance = null; + } } #endregion diff --git a/RGB.NET.Devices.Razer/RazerDeviceProvider.cs b/RGB.NET.Devices.Razer/RazerDeviceProvider.cs index 05c18c1..54cabf8 100644 --- a/RGB.NET.Devices.Razer/RazerDeviceProvider.cs +++ b/RGB.NET.Devices.Razer/RazerDeviceProvider.cs @@ -19,11 +19,21 @@ public sealed class RazerDeviceProvider : AbstractRGBDeviceProvider { #region Properties & Fields + // ReSharper disable once InconsistentNaming + private static readonly object _lock = new(); + private static RazerDeviceProvider? _instance; /// /// Gets the singleton instance. /// - public static RazerDeviceProvider Instance => _instance ?? new RazerDeviceProvider(); + public static RazerDeviceProvider Instance + { + get + { + lock (_lock) + return _instance ?? new RazerDeviceProvider(); + } + } /// /// Gets a modifiable list of paths used to find the native SDK-dlls for x86 applications. @@ -254,7 +264,7 @@ public sealed class RazerDeviceProvider : AbstractRGBDeviceProvider { 0x0F13, RGBDeviceType.Unknown, "Lian Li O11", LedMappings.ChromaLink, RazerEndpointType.ChromaLink }, { 0x0F1D, RGBDeviceType.Unknown, "Mouse Bungee V3 Chroma", LedMappings.ChromaLink, RazerEndpointType.ChromaLink }, { 0x0F1F, RGBDeviceType.LedController, "Addressable RGB Controller", LedMappings.ChromaLink, RazerEndpointType.ChromaLink }, - + }; #endregion @@ -267,8 +277,11 @@ public sealed class RazerDeviceProvider : AbstractRGBDeviceProvider /// Thrown if this constructor is called even if there is already an instance of this class. public RazerDeviceProvider() { - if (_instance != null) throw new InvalidOperationException($"There can be only one instance of type {nameof(RazerDeviceProvider)}"); - _instance = this; + lock (_lock) + { + if (_instance != null) throw new InvalidOperationException($"There can be only one instance of type {nameof(RazerDeviceProvider)}"); + _instance = this; + } } #endregion @@ -344,15 +357,18 @@ public sealed class RazerDeviceProvider : AbstractRGBDeviceProvider /// protected override void Dispose(bool disposing) { - base.Dispose(disposing); + lock (_lock) + { + base.Dispose(disposing); - TryUnInit(); + TryUnInit(); - // DarthAffe 03.03.2020: Fails with an access-violation - verify if an unload is already triggered by uninit - //try { _RazerSDK.UnloadRazerSDK(); } - //catch { /* at least we tried */ } + // DarthAffe 03.03.2020: Fails with an access-violation - verify if an unload is already triggered by uninit + //try { _RazerSDK.UnloadRazerSDK(); } + //catch { /* at least we tried */ } - _instance = null; + _instance = null; + } } #endregion diff --git a/RGB.NET.Devices.SteelSeries/SteelSeriesDeviceProvider.cs b/RGB.NET.Devices.SteelSeries/SteelSeriesDeviceProvider.cs index eeeff1c..0bf1958 100644 --- a/RGB.NET.Devices.SteelSeries/SteelSeriesDeviceProvider.cs +++ b/RGB.NET.Devices.SteelSeries/SteelSeriesDeviceProvider.cs @@ -20,11 +20,21 @@ public sealed class SteelSeriesDeviceProvider : AbstractRGBDeviceProvider #region Properties & Fields + // ReSharper disable once InconsistentNaming + private static readonly object _lock = new(); + private static SteelSeriesDeviceProvider? _instance; /// /// Gets the singleton instance. /// - public static SteelSeriesDeviceProvider Instance => _instance ?? new SteelSeriesDeviceProvider(); + public static SteelSeriesDeviceProvider Instance + { + get + { + lock (_lock) + return _instance ?? new SteelSeriesDeviceProvider(); + } + } private const int VENDOR_ID = 0x1038; @@ -93,8 +103,11 @@ public sealed class SteelSeriesDeviceProvider : AbstractRGBDeviceProvider /// Thrown if this constructor is called even if there is already an instance of this class. public SteelSeriesDeviceProvider() { - if (_instance != null) throw new InvalidOperationException($"There can be only one instance of type {nameof(SteelSeriesDeviceProvider)}"); - _instance = this; + lock (_lock) + { + if (_instance != null) throw new InvalidOperationException($"There can be only one instance of type {nameof(SteelSeriesDeviceProvider)}"); + _instance = this; + } } #endregion @@ -135,12 +148,15 @@ public sealed class SteelSeriesDeviceProvider : AbstractRGBDeviceProvider /// protected override void Dispose(bool disposing) { - base.Dispose(disposing); + lock (_lock) + { + base.Dispose(disposing); - try { SteelSeriesSDK.Dispose(); } - catch { /* shit happens */ } + try { SteelSeriesSDK.Dispose(); } + catch { /* shit happens */ } - _instance = null; + _instance = null; + } } #endregion diff --git a/RGB.NET.Devices.WS281X/WS281XDeviceProvider.cs b/RGB.NET.Devices.WS281X/WS281XDeviceProvider.cs index 43077c8..e150028 100644 --- a/RGB.NET.Devices.WS281X/WS281XDeviceProvider.cs +++ b/RGB.NET.Devices.WS281X/WS281XDeviceProvider.cs @@ -16,11 +16,21 @@ public sealed class WS281XDeviceProvider : AbstractRGBDeviceProvider { #region Properties & Fields + // ReSharper disable once InconsistentNaming + private static readonly object _lock = new(); + private static WS281XDeviceProvider? _instance; /// /// Gets the singleton instance. /// - public static WS281XDeviceProvider Instance => _instance ?? new WS281XDeviceProvider(); + public static WS281XDeviceProvider Instance + { + get + { + lock (_lock) + return _instance ?? new WS281XDeviceProvider(); + } + } /// /// Gets a list of all defined device-definitions. @@ -39,8 +49,11 @@ public sealed class WS281XDeviceProvider : AbstractRGBDeviceProvider /// Thrown if this constructor is called even if there is already an instance of this class. public WS281XDeviceProvider() { - if (_instance != null) throw new InvalidOperationException($"There can be only one instance of type {nameof(WS281XDeviceProvider)}"); - _instance = this; + lock (_lock) + { + if (_instance != null) throw new InvalidOperationException($"There can be only one instance of type {nameof(WS281XDeviceProvider)}"); + _instance = this; + } } #endregion @@ -72,11 +85,14 @@ public sealed class WS281XDeviceProvider : AbstractRGBDeviceProvider /// protected override void Dispose(bool disposing) { - base.Dispose(disposing); + lock (_lock) + { + base.Dispose(disposing); - DeviceDefinitions.Clear(); + DeviceDefinitions.Clear(); - _instance = null; + _instance = null; + } } #endregion diff --git a/RGB.NET.Devices.Wooting/WootingDeviceProvider.cs b/RGB.NET.Devices.Wooting/WootingDeviceProvider.cs index 079ffb1..6d16b2f 100644 --- a/RGB.NET.Devices.Wooting/WootingDeviceProvider.cs +++ b/RGB.NET.Devices.Wooting/WootingDeviceProvider.cs @@ -16,11 +16,21 @@ public sealed class WootingDeviceProvider : AbstractRGBDeviceProvider { #region Properties & Fields + // ReSharper disable once InconsistentNaming + private static readonly object _lock = new(); + private static WootingDeviceProvider? _instance; /// /// Gets the singleton instance. /// - public static WootingDeviceProvider Instance => _instance ?? new WootingDeviceProvider(); + public static WootingDeviceProvider Instance + { + get + { + lock (_lock) + return _instance ?? new WootingDeviceProvider(); + } + } /// /// Gets a modifiable list of paths used to find the native SDK-dlls for x86 windows applications. @@ -57,8 +67,11 @@ public sealed class WootingDeviceProvider : AbstractRGBDeviceProvider /// Thrown if this constructor is called even if there is already an instance of this class. public WootingDeviceProvider() { - if (_instance != null) throw new InvalidOperationException($"There can be only one instance of type {nameof(WootingDeviceProvider)}"); - _instance = this; + lock (_lock) + { + if (_instance != null) throw new InvalidOperationException($"There can be only one instance of type {nameof(WootingDeviceProvider)}"); + _instance = this; + } } #endregion @@ -96,15 +109,18 @@ public sealed class WootingDeviceProvider : AbstractRGBDeviceProvider /// protected override void Dispose(bool disposing) { - base.Dispose(disposing); - - lock (_WootingSDK.SdkLock) + lock (_lock) { - try { _WootingSDK.UnloadWootingSDK(); } - catch { /* at least we tried */ } - } + base.Dispose(disposing); - _instance = null; + lock (_WootingSDK.SdkLock) + { + try { _WootingSDK.UnloadWootingSDK(); } + catch { /* at least we tried */ } + } + + _instance = null; + } } #endregion