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

@ -1,10 +1,9 @@

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using System.Threading;
using Timer = System.Timers.Timer;
using Crestron.SimplSharp.CrestronIO;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
@ -18,12 +17,27 @@ namespace PepperDash.Essentials.Core.Config;
/// </summary>
public class ConfigWriter
{
/// <summary>
/// The name of the subfolder where the config file will be written
/// </summary>
public const string LocalConfigFolder = "LocalConfig";
public const long WriteTimeout = 30000;
/// <summary>
/// The amount of time in milliseconds to wait after the last config update before writing the config file. This is to prevent multiple rapid updates from causing multiple file writes.
/// Default is 30 seconds.
/// </summary>
public const long WriteTimeoutInMs = 30000;
public static CTimer WriteTimer;
static CCriticalSection fileLock = new CCriticalSection();
private static Timer WriteTimer;
static readonly object _fileLock = new();
static ConfigWriter()
{
WriteTimer = new Timer(WriteTimeoutInMs);
WriteTimer.Elapsed += (s, e) => WriteConfigFile(null);
}
/// <summary>
/// Updates the config properties of a device
@ -53,6 +67,9 @@ public class ConfigWriter
return success;
}
/// <summary>
/// Updates the config properties of a device
/// </summary>
public static bool UpdateDeviceConfig(DeviceConfig config)
{
bool success = false;
@ -73,17 +90,20 @@ public class ConfigWriter
return success;
}
/// <summary>
/// Updates the config properties of a room
/// </summary>
public static bool UpdateRoomConfig(DeviceConfig config)
{
bool success = false;
var roomConfigIndex = ConfigReader.ConfigObject.Rooms.FindIndex(d => d.Key.Equals(config.Key));
var roomConfigIndex = ConfigReader.ConfigObject.Rooms.FindIndex(d => d.Key.Equals(config.Key));
if (roomConfigIndex >= 0)
if (roomConfigIndex >= 0)
{
ConfigReader.ConfigObject.Rooms[roomConfigIndex] = config;
Debug.LogMessage(LogEventLevel.Debug, "Updated room of device: '{0}'", config.Key);
Debug.LogMessage(LogEventLevel.Debug, "Updated config of room: '{0}'", config.Key);
success = true;
}
@ -98,10 +118,9 @@ public class ConfigWriter
/// </summary>
static void ResetTimer()
{
if (WriteTimer == null)
WriteTimer = new CTimer(WriteConfigFile, WriteTimeout);
WriteTimer.Reset(WriteTimeout);
WriteTimer.Stop();
WriteTimer.Interval = WriteTimeoutInMs;
WriteTimer.Start();
Debug.LogMessage(LogEventLevel.Debug, "Config File write timer has been reset.");
}
@ -120,10 +139,10 @@ public class ConfigWriter
}
/// <summary>
/// Writes
/// Writes the specified configuration data to a file.
/// </summary>
/// <param name="filepath"></param>
/// <param name="o"></param>
/// <param name="filePath">The path of the file to write to.</param>
/// <param name="configData">The configuration data to write.</param>
public static void WriteFile(string filePath, string configData)
{
if (WriteTimer != null)
@ -133,9 +152,11 @@ public class ConfigWriter
Debug.LogMessage(LogEventLevel.Information, "Attempting to write config file: '{0}'", filePath);
var lockAcquired = false;
try
{
if (fileLock.TryEnter())
lockAcquired = Monitor.TryEnter(_fileLock);
if (lockAcquired)
{
using (StreamWriter sw = new StreamWriter(filePath))
{
@ -154,11 +175,8 @@ public class ConfigWriter
}
finally
{
if (fileLock != null && !fileLock.Disposed)
fileLock.Leave();
if (lockAcquired)
Monitor.Exit(_fileLock);
}
}
}