Aggiunta di un workerThread fuori dai thread UI x gestione più corretta display & co

This commit is contained in:
Samuele Locatelli
2026-01-02 11:51:55 +01:00
parent bdd876dad4
commit 9ef8d1ddcc
4 changed files with 204 additions and 75 deletions
+8 -4
View File
@@ -477,12 +477,16 @@ namespace IOB_UT_NEXT
public static string CRS(string key)
{
string answ = "";
try
if (ConfigurationManager.AppSettings.Count > 0)
{
answ = ConfigurationManager.AppSettings[key].ToString();
try
{
answ = ConfigurationManager.AppSettings[key].ToString();
}
catch
{ }
}
catch
{ }
return answ;
}
+193 -68
View File
@@ -15,6 +15,7 @@ using System.Security.Policy;
using System.Text;
using System.Threading;
using System.Windows.Forms;
using static System.Windows.Forms.VisualStyles.VisualStyleElement.Window;
namespace IOB_WIN_FORM
{
@@ -175,13 +176,13 @@ namespace IOB_WIN_FORM
// Start timer periodico comunicazione
gather.Interval = IOBConfFull.General.Timers.MsUI;
gather.Enabled = true;
displayTaskAndLog($"Main timer set: {gather.Interval}ms", true);
displayTaskAndLog($"Main UI timer set: {gather.Interval}ms", true);
// Start timer periodico interfaccia
displTimer.Interval = utils.CRI("timerIntMs");
displTimer.Enabled = true;
displayTaskAndLog("Program Running", true);
displayTaskAndLog("UI Program Running", true);
// check oggetto not null
if (iobObj != null)
@@ -218,10 +219,103 @@ namespace IOB_WIN_FORM
{
lgError($"AdapterForm: EXCEPTION in fase di chiamata URL di reboot:{iobObj.urlReboot}{Environment.NewLine}{exc}");
}
// avvio timer secondario x esecuzione (periodo di base: VHF!!!)
workerTimer = new System.Threading.Timer(_ =>
{
DoExecTasks();
}, null, 0, IOBConfFull.General.Timers.MsVHF);
displayTaskAndLog($"Main workerTimer set: {IOBConfFull.General.Timers.MsVHF}ms", true);
}
displayTaskAndLog("Main Form OK", true);
}
/// <summary>
/// Metodo principale esecuzione task in thread background (no interferenza con UI) x processi IO bound
/// </summary>
private void DoExecTasks()
{
bool doLog = false;
// procedo!
if (iobObj.periodicLog)
{
doLog = true;
}
try
{
#if false
refreshFormData();
#endif
// check esecuzione SendTask (MsVHF) COMUNQUE...
iobObj.getAndSend(gatherCycle.VHF);
// eseguo cicli attivi SOLO se adapter è in EFFETTIVO running...
if (iobObj.adpRunning)
{
if (iobObj.connectionOk)
{
// se richiesto faccio memory DUMP INIZIALE!
if (iobObj.doStartMemDump)
{
lgInfo("Inizio dump memoria");
iobObj.saveMemDump(dumpType.STARTUP);
// fatto! non ripeto...
iobObj.doStartMemDump = false;
lgInfo("Finito dump memoria");
}
// controllo se sia abilitato sampleDump della meoria (periodico)
if (iobObj.doSampleMemory)
{
checkSampleMem();
}
// controllo TUTTE le scadenze...
checkScad();
if (utils.CRI("waitEndCycle") > 0)
{
Thread.Sleep(utils.CRI("waitEndCycle"));
}
}
else
{
// qui attende meno...
DateTime dtVeto = lastStartTry.AddMilliseconds(waitRecMSec / 2);
if (iobObj.adpTryRestart && (DateTime.Now > dtVeto))
{
if (doLog)
{
lgInfo($"Retry Time Elapsed ({waitRecMSec / 2} ms)--> tryConnect");
}
lastStartTry = DateTime.Now;
iobObj.tryConnect();
}
}
}
else
{
if (doLog)
{
lgInfo("Adapter stopped");
}
// verifico SE debba tentare il riavvio, ovvero NON running ma adpTryRestart
// e non ho riprovato x oltre waitRecMSec
DateTime dtVeto = lastStartTry.AddMilliseconds(waitRecMSec);
if (iobObj.adpTryRestart && (DateTime.Now > dtVeto))
{
lastStartTry = DateTime.Now;
avviaAdapter(chkForceDequeue.Checked);
}
}
}
catch (Exception exc)
{
lgError(string.Format("Eccezione in fase di gatherTick: {0}{1}", Environment.NewLine, exc));
}
}
/// <summary>
/// Timer principale di esecuzione tasks in background
/// </summary>
protected System.Threading.Timer workerTimer;
#endregion Public Constructors
#region Private Delegates
@@ -295,7 +389,10 @@ namespace IOB_WIN_FORM
_commPlcActive = value;
// se true --> comunica/verde, altrimenti grigio
lblCNC.ForeColor = value ? Color.SeaGreen : Color.Black;
statusStrip1.Refresh();
this.UIThread(delegate
{
statusStrip1.Refresh();
});
}
}
@@ -328,7 +425,10 @@ namespace IOB_WIN_FORM
default:
break;
}
statusStrip1.Refresh();
this.UIThread(delegate
{
statusStrip1.Refresh();
});
}
}
@@ -721,8 +821,11 @@ namespace IOB_WIN_FORM
var newColor = decSemaforo(value);
if (newColor != bIN.BackColor)
{
bIN.BackColor = newColor;
bIN.Refresh();
this.UIThread(delegate
{
bIN.BackColor = newColor;
bIN.Refresh();
});
}
}
}
@@ -742,8 +845,11 @@ namespace IOB_WIN_FORM
var newColor = decSemaforo(value);
if (newColor != bOUT.BackColor)
{
bOUT.BackColor = newColor;
bOUT.Refresh();
this.UIThread(delegate
{
bOUT.BackColor = newColor;
bOUT.Refresh();
});
}
}
}
@@ -767,8 +873,11 @@ namespace IOB_WIN_FORM
{
logTaskString = logTaskString.Take(nLine2show).ToList();
}
lblTaskLog.Text = string.Join(Environment.NewLine, logTaskString);
lblTaskLog.Refresh();
this.UIThread(delegate
{
lblTaskLog.Text = string.Join(Environment.NewLine, logTaskString);
lblTaskLog.Refresh();
});
}
catch (Exception exc)
{
@@ -977,6 +1086,12 @@ namespace IOB_WIN_FORM
start.Enabled = false;
stop.Enabled = true;
restart.Enabled = true;
// 2026.01.02 fix timers al restart
gather.Enabled = true;
if (workerTimer != null)
{
workerTimer.Change(0, IOBConfFull.General.Timers.MsVHF);
}
displayTaskAndLog("Start Timers", true);
// inizializzo le scadenze dei timers...
@@ -1064,67 +1179,70 @@ namespace IOB_WIN_FORM
/// <param name="currDispData"></param>
public void updateFormDisplay(newDisplayData currDispData)
{
// ciclo x ogni oggetto x caricare le innovazioni...
if (currDispData != null && currDispData.hasData)
this.UIThread(delegate
{
DateTime adesso = DateTime.Now;
// RealTime display
if (!string.IsNullOrWhiteSpace(currDispData.newInData))
// ciclo x ogni oggetto x caricare le innovazioni...
if (currDispData != null && currDispData.hasData)
{
dataMonitor_0 = currDispData.newInData;
}
if (!string.IsNullOrWhiteSpace(currDispData.newSignalData))
{
dataMonitor_1 = currDispData.newSignalData;
}
if (!string.IsNullOrWhiteSpace(currDispData.newFLogData))
{
dataMonitor_3 = currDispData.newFLogData;
}
if (!string.IsNullOrWhiteSpace(currDispData.newUrlCallData))
{
dataMonitor_2 = currDispData.newUrlCallData;
}
DateTime adesso = DateTime.Now;
// RealTime display
if (!string.IsNullOrWhiteSpace(currDispData.newInData))
{
dataMonitor_0 = currDispData.newInData;
}
if (!string.IsNullOrWhiteSpace(currDispData.newSignalData))
{
dataMonitor_1 = currDispData.newSignalData;
}
if (!string.IsNullOrWhiteSpace(currDispData.newFLogData))
{
dataMonitor_3 = currDispData.newFLogData;
}
if (!string.IsNullOrWhiteSpace(currDispData.newUrlCallData))
{
dataMonitor_2 = currDispData.newUrlCallData;
}
// Bitmap lettura attuale
if (currDispData.counter >= 0)
{
if (logCounterVeto < adesso || lblCounter.Text != $"{currDispData.counter}")
// Bitmap lettura attuale
if (currDispData.counter >= 0)
{
lblCounter.Text = $"{currDispData.counter}";
lblCounter.Refresh();
logCounterVeto = adesso.AddMilliseconds(delayShowLogMs);
if (logCounterVeto < adesso || lblCounter.Text != $"{currDispData.counter}")
{
lblCounter.Text = $"{currDispData.counter}";
lblCounter.Refresh();
logCounterVeto = adesso.AddMilliseconds(delayShowLogMs);
}
}
// Bitmap lettura attuale
if (!string.IsNullOrWhiteSpace(currDispData.currBitmap))
{
lblBitmap.Text = currDispData.currBitmap;
lblBitmap.Refresh();
}
// LiveLog
if (!string.IsNullOrWhiteSpace(currDispData.newLiveLogData))
{
logWatcher = currDispData.newLiveLogData;
}
// semafori
if (currDispData.semOut != Semaforo.ND)
{
// aggiorno SE diverso
if (sOUT != currDispData.semOut)
{
sOUT = currDispData.semOut;
}
}
if (currDispData.semIn != Semaforo.ND)
{
//aggiorno SE diverso
if (sIN != currDispData.semIn)
{
sIN = currDispData.semIn;
}
}
}
// Bitmap lettura attuale
if (!string.IsNullOrWhiteSpace(currDispData.currBitmap))
{
lblBitmap.Text = currDispData.currBitmap;
lblBitmap.Refresh();
}
// LiveLog
if (!string.IsNullOrWhiteSpace(currDispData.newLiveLogData))
{
logWatcher = currDispData.newLiveLogData;
}
// semafori
if (currDispData.semOut != Semaforo.ND)
{
// aggiorno SE diverso
if (sOUT != currDispData.semOut)
{
sOUT = currDispData.semOut;
}
}
if (currDispData.semIn != Semaforo.ND)
{
//aggiorno SE diverso
if (sIN != currDispData.semIn)
{
sIN = currDispData.semIn;
}
}
}
});
}
public void WriteTextSafe(string text)
@@ -1157,7 +1275,10 @@ namespace IOB_WIN_FORM
protected void IobObj_eh_refreshed(object sender, iobRefreshedEventArgs e)
{
// aggiorno!
updateFormDisplay(e.DisplayDataObject);
this.UIThread(delegate
{
updateFormDisplay(e.DisplayDataObject);
});
}
/// <summary>
@@ -1462,6 +1583,7 @@ namespace IOB_WIN_FORM
displTimer?.Dispose();
gather?.Stop();
gather?.Dispose();
workerTimer?.Dispose();
}
private void displTimer_Tick(object sender, EventArgs e)
@@ -1490,6 +1612,7 @@ namespace IOB_WIN_FORM
if (stopTimer)
{
gather.Enabled = false;
workerTimer.Change(Timeout.Infinite, Timeout.Infinite);
}
newDisplayData currDispData = new newDisplayData();
@@ -1554,8 +1677,9 @@ namespace IOB_WIN_FORM
try
{
refreshFormData();
#if false
// check esecuzione SendTask (MsVHF) COMUNQUE...
iobObj.getAndSend(gatherCycle.VHF);
iobObj.getAndSend(gatherCycle.VHF);
// eseguo cicli attivi SOLO se adapter è in EFFETTIVO running...
if (iobObj.adpRunning)
{
@@ -1612,6 +1736,7 @@ namespace IOB_WIN_FORM
avviaAdapter(chkForceDequeue.Checked);
}
}
#endif
}
catch (Exception exc)
{
+1 -1
View File
@@ -4,7 +4,7 @@ using System.Windows.Forms;
namespace IOB_WIN_FORM
{
/// <summary>
/// Helper gestione UITHread e deleghe
/// Helper gestione UIThread e deleghe
/// https://www.codeproject.com/Articles/37642/Avoiding-InvokeRequired
/// </summary>
internal static class ControlExtensions
+2 -2
View File
@@ -20,9 +20,9 @@ CLI_INST=SteamWareSim
;STARTLIST=SIMUL_01
;STARTLIST=SHELLY_01
;STARTLIST=SHELLY_Pro3EM
;STARTLIST=SIMUL_03_SHELLY
STARTLIST=SIMUL_03_SHELLY
;STARTLIST=SIMUL_04_SHELLY
;STARTLIST=SIMUL_05_SHELLY
STARTLIST=i727_SHELLY
;STARTLIST=i727_SHELLY
MAXCNC=10