refactor: Refactor DeviceManager and related classes to improve thread safety and performance

- Replaced CCriticalSection with lock statements in DeviceManager for better thread management.
- Updated AddDevice and RemoveDevice methods to use Monitor for locking.
- Enhanced event handling for device activation and registration.
- Modified FileIO class to utilize Task for asynchronous file operations instead of CrestronInvoke.
- Improved feedback mechanisms in FeedbackBase and SystemMonitorController using Task.Run.
- Refactored GenericQueue to remove Crestron threading dependencies and utilize System.Threading.
- Updated BlueJeansPc and VideoCodecBase classes to use Task for asynchronous operations.
- Cleaned up unnecessary critical sections and improved code documentation across various files.
This commit is contained in:
Neil Dorin 2026-03-10 17:30:59 -06:00
parent 426ef4ad6b
commit 346a5e9e57
23 changed files with 998 additions and 912 deletions

View file

@ -3,6 +3,8 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using Crestron.SimplSharp;
using Crestron.SimplSharp.CrestronSockets;
using PepperDash.Core.Logging;
@ -277,7 +279,7 @@ public class GenericSecureTcpIpClient : Device, ISocketStatusWithStreamDebugging
/// <summary>
/// Queue lock
/// </summary>
CCriticalSection DequeueLock = new CCriticalSection();
private readonly object _dequeueLock = new();
/// <summary>
/// Receive Queue size. Defaults to 20. Will set to 20 if QueueSize property is less than 20. Use constructor or set queue size property before
@ -696,9 +698,8 @@ public class GenericSecureTcpIpClient : Device, ISocketStatusWithStreamDebugging
//Check to see if there is a subscription to the TextReceivedQueueInvoke event. If there is start the dequeue thread.
if (handler != null)
{
var gotLock = DequeueLock.TryEnter();
if (gotLock)
CrestronInvoke.BeginInvoke((o) => DequeueEvent());
if (Monitor.TryEnter(_dequeueLock))
Task.Run(() => DequeueEvent());
}
}
else //JAG added this as I believe the error return is 0 bytes like the server. See help when hover on ReceiveAsync
@ -708,7 +709,7 @@ public class GenericSecureTcpIpClient : Device, ISocketStatusWithStreamDebugging
}
/// <summary>
/// This method gets spooled up in its own thread an protected by a CCriticalSection to prevent multiple threads from running concurrently.
/// This method gets spooled up in its own thread an protected by a lock to prevent multiple threads from running concurrently.
/// It will dequeue items as they are enqueued automatically.
/// </summary>
void DequeueEvent()
@ -730,11 +731,8 @@ public class GenericSecureTcpIpClient : Device, ISocketStatusWithStreamDebugging
{
this.LogError(e, "DequeueEvent error: {0}", e.Message);
}
// Make sure to leave the CCritical section in case an exception above stops this thread, or we won't be able to restart it.
if (DequeueLock != null)
{
DequeueLock.Leave();
}
// Make sure to release the lock in case an exception above stops this thread, or we won't be able to restart it.
Monitor.Exit(_dequeueLock);
}
void HeartbeatStart()