From 25b252113b00a1cd7b499255994b1316bdbe43cd Mon Sep 17 00:00:00 2001 From: Samuele Locatelli Date: Fri, 28 Nov 2025 08:47:48 +0100 Subject: [PATCH] Aggiunto XML commento metodi --- IOB-MAN/BlazorForm.cs | 245 ++++++++++++++++++++++++++++++++--------- IOB-MAN/IOB-MAN.csproj | 2 +- 2 files changed, 193 insertions(+), 54 deletions(-) diff --git a/IOB-MAN/BlazorForm.cs b/IOB-MAN/BlazorForm.cs index cff0ddc..cbd48a9 100644 --- a/IOB-MAN/BlazorForm.cs +++ b/IOB-MAN/BlazorForm.cs @@ -1,4 +1,17 @@ -using IOB_MAN.Core.Services; +/// +/// Main Windows Forms host for the Blazor application. +/// This class serves as the entry point for the desktop application, integrating Blazor WebViews +/// with background services, memory monitoring, and auto-restart logic. +/// +/// Key Responsibilities: +/// - Initializes and hosts a Blazor WebAssembly UI via Windows Forms BlazorWebView. +/// - Manages lifecycle events: startup, form closing, and shutdown. +/// - Monitors .NET memory usage and system memory to prevent memory leaks or out-of-memory crashes. +/// - Implements periodic checks for auto-restart based on configuration and GC behavior. +/// - Listens to external signals (e.g., config updates, reload/reboot requests) from services. +/// - Gracefully shuts down all managed processes on exit or restart. +/// +using IOB_MAN.Core.Services; using Microsoft.AspNetCore.Components.WebView.WindowsForms; using Microsoft.Extensions.DependencyInjection; using NLog; @@ -11,6 +24,10 @@ namespace IOB_MAN { #region Public Constructors + /// + /// Initializes a new instance of the BlazorForm class. + /// Sets up the form, initializes services, configures Blazor view, and starts background timers. + /// public BlazorForm() { InitializeComponent(); @@ -26,8 +43,16 @@ namespace IOB_MAN #region Public Methods /// - /// Force restart application, with delay + /// Forces a restart of the application with an optional delay. + /// + /// Behavior: + /// - If 'force' is true, logs a forced restart (e.g., due to critical error). + /// - Otherwise, triggers restart due to consecutive GC thresholds being exceeded. + /// - Stops all running sub-processes via ACService.DoCloseAll(). + /// - Delays restart using cmd.exe timeout to ensure clean exit of current instance. + /// - Uses Application.Exit() to terminate the current process safely. /// + /// If true, performs a forced restart; otherwise, triggers restart due to GC exhaustion. public static void RestartApplication(bool force) { if (force) @@ -38,12 +63,14 @@ namespace IOB_MAN { Log.Info($"Chiamata restart application x superamento soglia GC consecutivi"); } + string exePath = Application.ExecutablePath; - // fermo tutti i sw controllati... + + // Close all managed services (e.g., external SWs) before restart ACService.DoCloseAll(false); Log.Info($"Completata chiusura processi x restart"); - // Use cmd.exe to delay start until current app exits + // Delay restart by 5 seconds using cmd.exe to avoid immediate re-launch int restartDelay = 5; ProcessStartInfo psi = new ProcessStartInfo("cmd.exe", $"/C timeout /t {restartDelay} & start \"\" \"{exePath}\"") { @@ -54,7 +81,7 @@ namespace IOB_MAN Process.Start(psi); Log.Info($"Avviato task di riavvio post delay {restartDelay}sec"); - // Now safely exit the current instance + // Exit current instance after delay Application.Exit(); } @@ -63,7 +90,8 @@ namespace IOB_MAN #region Protected Fields /// - /// Dataora prossima scadenza riavvio automatico + /// The next scheduled time for automatic restart check (based on configuration). + /// Used to determine when auto-restart should be triggered. /// protected DateTime tOutAutocheck = DateTime.Now; @@ -72,28 +100,43 @@ namespace IOB_MAN #region Private Fields /// - /// Classe logger + /// Logger instance for structured logging throughout the application. /// private static Logger Log = LogManager.GetCurrentClassLogger(); + /// + /// Counter tracking consecutive GC collections. + /// Used to detect prolonged memory pressure and trigger forced restart if threshold exceeded. + /// private int currSeqGC = 0; /// - /// Memoria dotNet allocata + /// Total managed memory allocated by the .NET runtime (in bytes). + /// Monitored to detect memory pressure and trigger GC or restart. /// private long dotNetMemUsed = 0; + /// + /// Timestamp of the last forced GC collection. + /// Used to enforce periodic GC even if memory is not critically high. + /// private DateTime LastForcedGC = DateTime.Now; + /// + /// Maximum number of consecutive GC collections allowed before triggering restart. + /// Default is 5 — if exceeded, application restarts to prevent memory exhaustion. + /// private int maxConsGC = 5; /// - /// Max memoria consumabile (std 128Mb) + /// Maximum allowed memory consumption (in MB) for the application. + /// Default is 128 MB — if managed or total memory exceeds half of this, triggers GC or restart. /// private double maxMemoryLimitMb = 128.0; /// - /// Memoria totale processo + /// Total private memory used by the current process (in bytes). + /// Used to detect system-level memory pressure. /// private long totalMemUsed = 0; @@ -101,17 +144,32 @@ namespace IOB_MAN #region Private Properties + /// + /// Singleton service for application control (e.g., managing external services, config, restarts). + /// private static AppControlService ACService { get; set; } = null!; + /// + /// Singleton service for handling flux log requests and UI interactions. + /// private static FluxLogManService FLMService { get; set; } = null!; + /// + /// Converts .NET managed memory (bytes) to MB for logging and display. + /// private double dotNetMemUsedMb { get => dotNetMemUsed / 1024.0 / 1024.0; } + /// + /// Stores the last known size of the form to maintain consistent positioning. + /// private Size lastSize { get; set; } = new Size(1200, 700); + /// + /// Converts total process memory (bytes) to MB for logging and display. + /// private double totalMemUsedMb { get => totalMemUsed / 1024.0 / 1024.0; @@ -122,22 +180,29 @@ namespace IOB_MAN #region Private Methods /// - /// Esecuzione del processo di restart + /// Executes a restart of the application. + /// + /// Behavior: + /// - If 'fullRestart' is true, launches an external restarter (EgwAccRestarter.exe). + /// - Otherwise, uses Application.Restart() to restart the current app (without external update check). /// + /// If true, uses external restarter; otherwise, restarts current app. private static void DoRestart(bool fullRestart) { - // full restart usa sw esterno, altrimenti solo app che riparte SENZA check update esterno if (fullRestart) { - // uso restarter esterno... + // Launch external restarter (e.g., for complex service restarts) Assembly assembly = Assembly.GetExecutingAssembly(); string startDir = Path.GetDirectoryName(assembly.Location)!; string extPath = Path.Combine(startDir, "libs", "EgwAccRestarter.exe"); - // uso processstartInfo x nascondere finestra - ProcessStartInfo startInfo = new ProcessStartInfo(); - startInfo.WindowStyle = ProcessWindowStyle.Normal; - startInfo.CreateNoWindow = true; - startInfo.FileName = extPath; + + ProcessStartInfo startInfo = new ProcessStartInfo + { + WindowStyle = ProcessWindowStyle.Normal, + CreateNoWindow = true, + FileName = extPath + }; + Process.Start(startInfo); } else @@ -148,9 +213,12 @@ namespace IOB_MAN } /// - /// Riavvio il timer... + /// Handles configuration updates from the AppControlService. + /// + /// Actions: + /// - Stops and restarts timers to reflect new refresh intervals. + /// - Updates the auto-restart check time from configuration. /// - /// private void ACService_EA_ConfigUpdated() { timerUI.Stop(); @@ -159,6 +227,14 @@ namespace IOB_MAN StartTimer(); } + /// + /// Handles a reboot request from the AppControlService. + /// + /// Actions: + /// - Stops all timers and services. + /// - Closes all external processes. + /// - Triggers a forced restart. + /// private void ACService_EA_RebootRequested() { Log.Info("---------------------------------------"); @@ -172,21 +248,36 @@ namespace IOB_MAN RestartApplication(true); } + /// + /// Handles a reload request from the AppControlService. + /// + /// Action: + /// - Restarts the application without closing external services (partial reload). + /// private void ACService_EA_ReloadRequested() { - // effettua chiamata reload DoRestart(false); } /// - /// Gestione evento restart applicazione + /// Handles a restart request from the AppControlService. + /// + /// Action: + /// - Triggers a full restart (using external restarter). /// private void ACService_EA_RestartRequested() { - // effettua chiamata restart DoRestart(true); } + /// + /// Cleans up event handlers and resources when the form is closing. + /// + /// Actions: + /// - Removes event subscriptions from services. + /// - Stops and disposes timers. + /// - Closes all external processes. + /// private void BlazorForm_FormClosing(object sender, FormClosingEventArgs e) { ACService.EA_ConfigUpdated -= ACService_EA_ConfigUpdated; @@ -202,33 +293,39 @@ namespace IOB_MAN } /// - /// Evento completamento caricamento app + /// Sets the form's position to center-bottom of the screen workspace. + /// Ensures consistent placement across different screen configurations. /// - /// - /// private void BlazorForm_Load(object sender, EventArgs e) { SetPosition(); } /// - /// effettua controllo memoria + log - /// se occupa più di maxMemoryLimitMb --> chiama GC + /// Periodically checks memory usage and triggers GC if thresholds are exceeded. + /// + /// Logic: + /// - Measures managed and total memory. + /// - If managed memory exceeds half of maxMemoryLimitMb OR total memory exceeds maxMemoryLimitMb: + /// - Forces GC collection. + /// - Increments consecutive GC counter. + /// - If counter exceeds maxConsGC → triggers restart. + /// - If more than 1 hour has passed since last forced GC → triggers periodic GC. + /// - Otherwise, decrements counter to prevent overcounting. /// private void CheckMemory() { - dotNetMemUsed = GC.GetTotalMemory(false); // Pass 'true' to force a garbage collection first + dotNetMemUsed = GC.GetTotalMemory(false); Process currentProcess = Process.GetCurrentProcess(); totalMemUsed = currentProcess.PrivateMemorySize64; Log.Info($"Memory Usage | {dotNetMemUsedMb:F2} / {totalMemUsedMb:F2} MB | Managed / Total"); + if (dotNetMemUsedMb > maxMemoryLimitMb / 2 || totalMemUsedMb > maxMemoryLimitMb) { - // chiamo GC forzatamente currSeqGC++; Log.Info($"Chiamato forzatamente GC.Collect per superamento limite memoria | count: {currSeqGC}"); GC.Collect(); - // registro forced GC LastForcedGC = DateTime.Now; if (currSeqGC > maxConsGC) { @@ -239,10 +336,8 @@ namespace IOB_MAN } else if (DateTime.Now.Subtract(LastForcedGC).TotalHours > 1) { - // chiamo GC forzatamente Log.Info($"Chiamato forzatamente GC.Collect per scadenza periodo"); GC.Collect(); - // registro forced GC LastForcedGC = DateTime.Now; } else @@ -256,25 +351,38 @@ namespace IOB_MAN } /// - /// Init conf accessorie + /// Initializes configuration values from the AppControlService. + /// + /// Specifically: sets maxMemoryLimitMb from configuration (e.g., MaxMemGc). /// private void ConfInit() { - // recupero limite memoria prima del GC maxMemoryLimitMb = ACService.MaxMemGc; } /// - /// Richiesta apertura nuova form x editing FluxLog: la implemento leggendo il codIOB e lo passo al controllo... + /// Handles a request to open a FluxLog editing form. + /// + /// Action: + /// - Creates and shows a new FluxLogData form with the provided codIOB. + /// - Enables user to edit or view flux logs for a specific IOB. /// - /// + /// The IOB code associated with the requested log. private void FLMService_EA_FluxLogReq(string codIOB) { - // chiamo nuova form con parametro x CodIOB richiesto FluxLogData FldForm = new FluxLogData(FLMService, codIOB); FldForm.Show(); } + /// + /// Initializes the Blazor WebView with required services and root components. + /// + /// Steps: + /// - Sets up a ServiceCollection with required dependencies. + /// - Registers AppControlService and FluxLogManService as singletons. + /// - Configures the BlazorWebView to load the index.html page. + /// - Adds MainBlazor component to the root element. + /// private void InitBlazorView() { Stopwatch sw = new Stopwatch(); @@ -296,13 +404,20 @@ namespace IOB_MAN } catch (Exception exc) { - Log.Error($"Exception during setartup{Environment.NewLine}{exc}"); + Log.Error($"Exception during startup{Environment.NewLine}{exc}"); } } + /// + /// Initializes core services (AppControlService, FluxLogManService). + /// + /// Registers event handlers for: + /// - Config updates + /// - Restart, reload, and reboot requests + /// - FluxLog request events + /// private void ServiceInit() { - //init preliminare servizio controllo ACService = new AppControlService(true); FLMService = new FluxLogManService(); ACService.EA_ConfigUpdated += ACService_EA_ConfigUpdated; @@ -312,31 +427,50 @@ namespace IOB_MAN FLMService.EA_FluxLogReq += FLMService_EA_FluxLogReq; } + /// + /// Centers the form in the bottom-left of the screen workspace. + /// Ensures consistent UI placement regardless of screen resolution. + /// private void SetPosition() { - // posiziono in basso a sx... Rectangle workArea = Screen.GetWorkingArea(this); this.Location = new Point((workArea.Right - lastSize.Width) / 2, (workArea.Bottom - lastSize.Height) / 2); } + /// + /// Starts background timers based on configuration values from AppControlService. + /// + /// Timers: + /// - timerUI: scans application state at intervals (RefreshPeriod). + /// - timerTask: checks for auto-restart conditions (CheckRestartPeriod). + /// - timerMemCheck: monitors memory usage (CheckMemoryPeriod). + /// + /// Note: Delays start by 20–80ms to avoid race conditions during initialization. + /// private void StartTimer() { - // timer controlli da conf timerUI.Interval = (ACService.RefreshPeriod); timerTask.Interval = (ACService.CheckRestartPeriod); timerMemCheck.Interval = (ACService.CheckMemoryPeriod); - // avvio timers + timerUI.Start(); - Thread.Sleep(rand.Next(20,80)); + Thread.Sleep(rand.Next(20, 80)); timerTask.Start(); Thread.Sleep(rand.Next(20, 80)); timerMemCheck.Start(); } + /// + /// Random number generator for introducing slight delays in timer startup. + /// Used to prevent all timers from starting simultaneously. + /// private Random rand = new Random(); /// - /// Evento timer memory check periodico + /// Periodic memory check timer event. + /// + /// Triggers CheckMemory() to monitor memory usage and enforce GC if needed. + /// Also logs service statistics for debugging. /// /// /// @@ -347,34 +481,39 @@ namespace IOB_MAN } /// - /// Timer task x eventuale riavvio processi fermi SE abilitato... + /// Periodic task timer event. + /// + /// Actions: + /// - Stops the timer to avoid overlap. + /// - Checks for conditions to auto-restart external services. + /// - Restarts the timer to maintain continuous monitoring. /// /// /// private void timerTask_Tick(object sender, EventArgs e) { - // fermo task... timerTask.Stop(); - // esegue controllo task x eventuale autorestart ACService.DoAutoRestart(false); - // riavvio task x evitare sovrapposizioni in debug timerTask.Start(); } /// - /// Esecuzione task di verifica stato app + /// Periodic UI scan timer event. + /// + /// Actions: + /// - Stops the timer to avoid overlap. + /// - Executes ACService.DoScan() to check application state. + /// - Reinstates the timer to maintain continuous monitoring. /// /// /// private async void timerUI_Tick(object sender, EventArgs e) { - // fermo task... timerUI.Stop(); await ACService.DoScan(); - // riavvio task x evitare sovrapposizioni in debug timerUI.Start(); } #endregion Private Methods } -} \ No newline at end of file +} diff --git a/IOB-MAN/IOB-MAN.csproj b/IOB-MAN/IOB-MAN.csproj index 66e75cb..0689306 100644 --- a/IOB-MAN/IOB-MAN.csproj +++ b/IOB-MAN/IOB-MAN.csproj @@ -8,7 +8,7 @@ enable true enable - 4.0.2511.2718 + 4.0.2511.2807 Debug;Release;Remote_DEBUG false