diff --git a/Visual Studio Projects/ZWaveJS.NET/ZWaveJS.NET/Driver.cs b/Visual Studio Projects/ZWaveJS.NET/ZWaveJS.NET/Driver.cs index ca1fa40..d93047a 100644 --- a/Visual Studio Projects/ZWaveJS.NET/ZWaveJS.NET/Driver.cs +++ b/Visual Studio Projects/ZWaveJS.NET/ZWaveJS.NET/Driver.cs @@ -15,7 +15,7 @@ public class Driver internal static List UsedPorts = new List(); internal Websocket.Client.WebsocketClient ClientWebSocket; - internal Dictionary> Callbacks; + internal TSafeDictionary> Callbacks; internal bool Inited = false; internal ZWaveOptions Options; internal const string FWUSAPIKey = "921f8000486fcc2744721cfc747aab2db8fc025b5d487cbf2eba76e88ff6f79a064644bf"; @@ -574,7 +574,7 @@ public Driver(Uri Server, int SchemaVersion = 0, int ServerErrorThrottleTime = 1 _schemaVersion = SchemaVersion; } - Callbacks = new Dictionary>(); + Callbacks = new TSafeDictionary>(); MapEvents(); this.WSAddress = Server; @@ -607,7 +607,7 @@ public Driver(string SerialPort, ZWaveOptions Options, int ServerCommunicationPo settings.Converters.Add(new ZWJSSJsonConverter(this)); _jsonSerializer = JsonSerializer.Create(settings); - Callbacks = new Dictionary>(); + Callbacks = new TSafeDictionary>(); MapEvents(); this.SerialPort = SerialPort; diff --git a/Visual Studio Projects/ZWaveJS.NET/ZWaveJS.NET/Structures.cs b/Visual Studio Projects/ZWaveJS.NET/ZWaveJS.NET/Structures.cs index 92347fd..06011fa 100644 --- a/Visual Studio Projects/ZWaveJS.NET/ZWaveJS.NET/Structures.cs +++ b/Visual Studio Projects/ZWaveJS.NET/ZWaveJS.NET/Structures.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Concurrent; using System.Collections.Generic; using System.Dynamic; using System.IO; @@ -579,4 +580,45 @@ internal FirmwareUpdate() { } public string filename { get; internal set; } public int? firmwareTarget { get; internal set; } } + + /// + /// Thread-safe Dictionary + /// + /// + /// ConcurrentDictionary wrapper class exposing a partial + /// "Dictionary-like" interface for use in this application. + /// + public class TSafeDictionary { + + private ConcurrentDictionary _dictionary + = new ConcurrentDictionary(); + + public V this[K key] { + get { + if (!_dictionary.TryGetValue(key, out V value)) { + throw new KeyNotFoundException(); + } + return value; + } + private set { } + } + + public ICollection Keys { + get { return (_dictionary.Keys); } + } + + public void Add(K key, V callback) { + if (!_dictionary.TryAdd(key, callback)) { + throw new ArgumentException(); + } + } + + public Boolean Remove(K key) { + return _dictionary.TryRemove(key, out _); + } + + public Boolean ContainsKey(K key) { + return _dictionary.ContainsKey(key); + } + } } diff --git a/Visual Studio Projects/ZWaveJS.NET/ZWaveJS.NET/Websocket.Client/WebsocketClient.Sending.cs b/Visual Studio Projects/ZWaveJS.NET/ZWaveJS.NET/Websocket.Client/WebsocketClient.Sending.cs index 1967941..d4b0d83 100644 --- a/Visual Studio Projects/ZWaveJS.NET/ZWaveJS.NET/Websocket.Client/WebsocketClient.Sending.cs +++ b/Visual Studio Projects/ZWaveJS.NET/ZWaveJS.NET/Websocket.Client/WebsocketClient.Sending.cs @@ -58,6 +58,12 @@ public void Send(ArraySegment message) _messagesBinaryToSendQueue.Writer.TryWrite(message); } + /// + /// Synchronize the SendInstant calls to avoid + /// the documented issue with simultaneous usage. + /// + private Object _sendInstantLock = new Object(); + /// /// Send text message to the websocket channel. /// It doesn't use a sending queue, @@ -69,7 +75,9 @@ public Task SendInstant(string message) { Validations.Validations.ValidateInput(message, nameof(message)); - return SendInternalSynchronized(message); + lock (_sendInstantLock) { + return SendInternalSynchronized(message); + } } /// @@ -81,7 +89,9 @@ public Task SendInstant(string message) /// Message to be sent public Task SendInstant(byte[] message) { - return SendInternalSynchronized(new ArraySegment(message)); + lock (_sendInstantLock) { + return SendInternalSynchronized(new ArraySegment(message)); + } } ///