Update con prima separazione metodi pooled/single (da validare)
This commit is contained in:
@@ -80,7 +80,7 @@ namespace IOB_UT_NEXT.Config.Base
|
||||
/// <summary>
|
||||
/// Soglia massima errori prima della disconnessione automatica in check
|
||||
/// </summary>
|
||||
public int MaxErroriCheck { get; set; } = 100;
|
||||
public int MaxErroriCheck { get; set; } = 50;
|
||||
|
||||
/// <summary>
|
||||
/// Max tentativi ping permessi (default: 5)
|
||||
|
||||
@@ -274,7 +274,7 @@ namespace IOB_UT_NEXT.Config
|
||||
PzTotMode = fIni.ReadString("OPTPAR", "PZGTOT_MODE", ""),
|
||||
ReadErrorMax = fIni.ReadInteger("OPTPAR", "READ_ERROR_MAX", 20),
|
||||
ReadErrorSleepTime = fIni.ReadInteger("OPTPAR", "READ_ERROR_SLEEP_TIME", 20000),
|
||||
StartupVetoQueueIN = fIni.ReadInteger("OPTPAR", "VETO_QUEUE_IN", 10),
|
||||
StartupVetoQueueIN = fIni.ReadInteger("OPTPAR", "VETO_QUEUE_IN", 6),
|
||||
Vendor = fIni.ReadString("MACHINE", "VENDOR", "STEAMWARE"),
|
||||
Connect = new ConnectionDto()
|
||||
{
|
||||
|
||||
@@ -8,43 +8,40 @@ public class SingleThreadTaskScheduler : TaskScheduler, IDisposable
|
||||
{
|
||||
private readonly BlockingCollection<Task> _tasks = new BlockingCollection<Task>();
|
||||
private readonly Thread _thread;
|
||||
public SynchronizationContext SyncContext { get; private set; }
|
||||
|
||||
public SingleThreadTaskScheduler()
|
||||
public SingleThreadTaskScheduler(string threadName)
|
||||
{
|
||||
var tcs = new TaskCompletionSource<bool>();
|
||||
_thread = new Thread(() =>
|
||||
{
|
||||
// Creiamo il contesto di sincronizzazione personalizzato
|
||||
SyncContext = new SingleThreadSynchronizationContext(this);
|
||||
SynchronizationContext.SetSynchronizationContext(SyncContext);
|
||||
tcs.SetResult(true);
|
||||
|
||||
foreach (var task in _tasks.GetConsumingEnumerable())
|
||||
{
|
||||
// Esegue il task sul thread dedicato
|
||||
base.TryExecuteTask(task);
|
||||
}
|
||||
});
|
||||
|
||||
_thread.IsBackground = true;
|
||||
_thread.Name = "SingleWorkerThread";
|
||||
})
|
||||
{ IsBackground = true, Name = threadName };
|
||||
_thread.Start();
|
||||
tcs.Task.Wait(); // Aspetta che il thread sia pronto col suo contesto
|
||||
}
|
||||
|
||||
protected override void QueueTask(Task task)
|
||||
private class SingleThreadSynchronizationContext : SynchronizationContext
|
||||
{
|
||||
_tasks.Add(task);
|
||||
}
|
||||
|
||||
protected override bool TryExecuteTaskInline(Task task, bool taskWasPreviouslyQueued)
|
||||
{
|
||||
// Consente l'esecuzione inline solo se siamo già sul thread dedicato
|
||||
return Thread.CurrentThread == _thread && base.TryExecuteTask(task);
|
||||
}
|
||||
|
||||
protected override IEnumerable<Task> GetScheduledTasks()
|
||||
{
|
||||
return _tasks.ToArray();
|
||||
private readonly SingleThreadTaskScheduler _sch;
|
||||
public SingleThreadSynchronizationContext(SingleThreadTaskScheduler sch) => _sch = sch;
|
||||
public override void Post(SendOrPostCallback d, object state)
|
||||
=> Task.Factory.StartNew(() => d(state), CancellationToken.None, TaskCreationOptions.None, _sch);
|
||||
}
|
||||
|
||||
protected override void QueueTask(Task task) => _tasks.Add(task);
|
||||
protected override bool TryExecuteTaskInline(Task task, bool prev)
|
||||
=> Thread.CurrentThread == _thread && base.TryExecuteTask(task);
|
||||
protected override IEnumerable<Task> GetScheduledTasks() => _tasks;
|
||||
public override int MaximumConcurrencyLevel => 1;
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_tasks.CompleteAdding();
|
||||
}
|
||||
public void Dispose() => _tasks.CompleteAdding();
|
||||
}
|
||||
@@ -351,36 +351,6 @@ namespace IOB_UT_NEXT
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#if false
|
||||
/// <summary>
|
||||
/// Versione async della chiamata ad URL
|
||||
/// </summary>
|
||||
/// <param name="URL"></param>
|
||||
/// <returns></returns>
|
||||
public static string callUrlAsync(string URL)
|
||||
{
|
||||
// Chiamo in modalità task...
|
||||
var resp = Task.Run(() => callUrl(URL));
|
||||
resp.Wait();
|
||||
return resp.Result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Versione async della chiamata ad URL
|
||||
/// </summary>
|
||||
/// <param name="URL"></param>
|
||||
/// <param name="payload"></param>
|
||||
/// <returns></returns>
|
||||
public static string callUrlAsync(string URL, string payload)
|
||||
{
|
||||
// Chiamo in modalità task...
|
||||
var resp = Task.Run(() => callUrl(URL, payload));
|
||||
resp.Wait();
|
||||
return resp.Result;
|
||||
}
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Effettua chiamata URL IMMEDIATAMENTE e restituisce risultato
|
||||
/// </summary>
|
||||
@@ -553,20 +523,6 @@ namespace IOB_UT_NEXT
|
||||
public static string CRS(string key)
|
||||
{
|
||||
return ConfigurationManager.AppSettings[key] ?? string.Empty;
|
||||
#if false
|
||||
string answ = "";
|
||||
if (ConfigurationManager.AppSettings.Count > 0)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
||||
answ = ConfigurationManager.AppSettings[key].ToString();
|
||||
}
|
||||
catch
|
||||
{ }
|
||||
}
|
||||
return answ;
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -86,6 +86,12 @@ DISABLE_SEND_WDST=TRUE
|
||||
; bit da scrivere come trace ad ogni check
|
||||
;MEM_2_TRACE=|BIT3|BIT4|BIT5|
|
||||
PARAM_CONF=3028.json
|
||||
; test timing & errori
|
||||
timerIntMs=30
|
||||
ExeSingleThread=true
|
||||
MAX_ERR_CHECK=10
|
||||
;WAIT_REC_MSEC=15000
|
||||
|
||||
|
||||
[BRANCH]
|
||||
NAME=master
|
||||
|
||||
@@ -88,6 +88,10 @@ ENABLE_SEND_PZC_BLOCK=TRUE
|
||||
MIN_SEND_PZC_BLOCK=0
|
||||
MAX_SEND_PZC_BLOCK=100
|
||||
DISABLE_SEND_WDST=TRUE
|
||||
; test timing & errori
|
||||
timerIntMs=40
|
||||
;ExeSingleThread=true
|
||||
MAX_ERR_CHECK=10
|
||||
; bit da scrivere come trace ad ogni check
|
||||
;MEM_2_TRACE=|BIT3|BIT4|BIT5|
|
||||
PARAM_CONF=3029.json
|
||||
|
||||
@@ -26,11 +26,12 @@ CLI_INST=SteamWareSim
|
||||
;STARTLIST=3004
|
||||
;STARTLIST=3002
|
||||
;STARTLIST=GT575
|
||||
STARTLIST=3029
|
||||
;STARTLIST=3004,3005
|
||||
;STARTLIST=SIMUL_01
|
||||
;STARTLIST=FOV106
|
||||
;STARTLIST=FOV107
|
||||
;STARTLIST=3028
|
||||
STARTLIST=3029
|
||||
|
||||
|
||||
MAXCNC=10
|
||||
@@ -59,6 +59,11 @@ namespace IOB_WIN_FANUC.Iob
|
||||
MemBlockX = new byte[xSize];
|
||||
MemBlockY = new byte[ySize];
|
||||
|
||||
// forzo letture single threaded x FANUC!!!
|
||||
IOBConfFull.General.ExeSingleThread = true;
|
||||
// x FANUC riduco num errori std x forzare riavvio rapido
|
||||
maxErroriCheck = maxErroriCheck > 15 ? 15 : maxErroriCheck;
|
||||
|
||||
// loggo aree di memoria avviate...
|
||||
lgInfo($"Init area di memoria | MemBlockG: {gSize}b | MemBlockR: {rSize}b | MemBlockX: {xSize}b | MemBlockY: {ySize}b ");
|
||||
|
||||
@@ -1520,6 +1525,7 @@ namespace IOB_WIN_FANUC.Iob
|
||||
/// </summary>
|
||||
public override void tryConnect()
|
||||
{
|
||||
lgInfo("++++++++++++ CONNECT ++++++++++++");
|
||||
if (!connectionOk)
|
||||
{
|
||||
// controllo che il ping sia stato tentato almeno pingTestSec fa...
|
||||
@@ -1619,6 +1625,7 @@ namespace IOB_WIN_FANUC.Iob
|
||||
/// </summary>
|
||||
public override void tryDisconnect()
|
||||
{
|
||||
lgInfo("----------- DISCONNECT -----------");
|
||||
if (connectionOk)
|
||||
{
|
||||
string szStatusConnection = "";
|
||||
@@ -3008,13 +3015,19 @@ namespace IOB_WIN_FANUC.Iob
|
||||
|
||||
private void tryIncreaseErrorComm(string topic)
|
||||
{
|
||||
lgTrace($"[Thread: {Thread.CurrentThread.ManagedThreadId}] | numErroriCheck: {numErroriCheck}");
|
||||
numErroriCheck++;
|
||||
parentForm.ChangeErrorDelay(topic, numErroriCheck, 5);
|
||||
}
|
||||
|
||||
private void tryReduceErrorCount(string topic)
|
||||
{
|
||||
numErroriCheck = numErroriCheck > 0 ? numErroriCheck-- : numErroriCheck;
|
||||
numErroriCheck -= 1;
|
||||
if (numErroriCheck>=0)
|
||||
{
|
||||
lgTrace($"[Thread: {Thread.CurrentThread.ManagedThreadId}] | numErroriCheck: {numErroriCheck}");
|
||||
}
|
||||
numErroriCheck = numErroriCheck < 0 ? 0 : numErroriCheck;
|
||||
parentForm.ChangeErrorDelay(topic, numErroriCheck, -5);
|
||||
}
|
||||
|
||||
|
||||
+485
-86
@@ -275,7 +275,7 @@ namespace IOB_WIN_FORM
|
||||
{
|
||||
// update veto!
|
||||
dMonDisplVetoVeto[1] = adesso.AddMilliseconds(delayShowLogMs);
|
||||
|
||||
|
||||
if (!ShouldUpdateUI()) return;
|
||||
// se scaduto veto --> display!
|
||||
lblOutMessage.Text = String.Join(Environment.NewLine, dMonValues[1]);
|
||||
@@ -748,8 +748,14 @@ namespace IOB_WIN_FORM
|
||||
restart.Enabled = true;
|
||||
// 2026.01.02 fix timers al restart
|
||||
gather.Enabled = true;
|
||||
|
||||
// 2026.02.17 controlo stato single thread exe...
|
||||
doExeSingleThread = iobObj.IOBConfFull.General.ExeSingleThread;
|
||||
|
||||
#if true
|
||||
// gestione worker
|
||||
StartWorker();
|
||||
#endif
|
||||
displayTaskAndLog("Start Timers", true);
|
||||
// inizializzo le scadenze dei timers...
|
||||
TimersVeto = new Dictionary<gatherCycle, DateTime>();
|
||||
@@ -788,6 +794,31 @@ namespace IOB_WIN_FORM
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Registra variazione error delay in caso di errori o successi
|
||||
/// </summary>
|
||||
/// <param name="topic"></param>
|
||||
/// <param name="currCount"></param>
|
||||
/// <param name="delta"></param>
|
||||
public void ChangeErrorDelay(string topic, int currCount, int delta)
|
||||
{
|
||||
_errorDelay += delta;
|
||||
// se fosse negativo --> riporto a zero!
|
||||
_errorDelay = _errorDelay < 0 ? 0 : _errorDelay;
|
||||
// registro LOG variazione
|
||||
if (delta > 0)
|
||||
{
|
||||
lgTrace($"[Thread: {Thread.CurrentThread.ManagedThreadId}] | +++ delay {_errorDelay} | {topic} | err: {currCount} | {DateTime.Now:HH:mm:ss.fff}");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_errorDelay > 0)
|
||||
{
|
||||
lgTrace($"[Thread: {Thread.CurrentThread.ManagedThreadId}] | --- delay {_errorDelay} | {topic} | err: {currCount} | {DateTime.Now:HH:mm:ss.fff}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// mostra un testo sulla status bar + LOG
|
||||
/// </summary>
|
||||
@@ -1084,6 +1115,28 @@ namespace IOB_WIN_FORM
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Esegue logica di init async x IOB
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
protected async Task<bool> iobInitAsync()
|
||||
{
|
||||
try
|
||||
{
|
||||
this.Cursor = Cursors.WaitCursor;
|
||||
await iobObj.InitializeAsync();
|
||||
this.Cursor = Cursors.Default;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
lgError($"Inizializzazione fallita per {tipoScelto}: {ex.Message}");
|
||||
iobObj = null; // Evitiamo di usare un oggetto malfunzionante
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// GEstione evento refresh
|
||||
/// </summary>
|
||||
@@ -1184,28 +1237,6 @@ namespace IOB_WIN_FORM
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Esegue logica di init async x IOB
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
protected async Task<bool> iobInitAsync()
|
||||
{
|
||||
try
|
||||
{
|
||||
this.Cursor = Cursors.WaitCursor;
|
||||
await iobObj.InitializeAsync();
|
||||
this.Cursor = Cursors.Default;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
lgError($"Inizializzazione fallita per {tipoScelto}: {ex.Message}");
|
||||
iobObj = null; // Evitiamo di usare un oggetto malfunzionante
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Init form (grafica) con helper x testi e varie
|
||||
/// </summary>
|
||||
@@ -1248,25 +1279,6 @@ namespace IOB_WIN_FORM
|
||||
nLine2show = utils.CRI("numRowConsole");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Indica se debba aggiornare o meno la UI perché minimizzata o meno
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private bool ShouldUpdateUI()
|
||||
{
|
||||
// 1. Controlla se la form stessa è minimizzata
|
||||
if (this.WindowState == FormWindowState.Minimized) return false;
|
||||
|
||||
// 2. Se è una MDI Child, controlla se il Padre è minimizzato
|
||||
if (this.MdiParent != null && this.MdiParent.WindowState == FormWindowState.Minimized)
|
||||
return false;
|
||||
|
||||
// 3. (Opzionale) Controlla se la form è visibile
|
||||
if (!this.Visible) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// MOstra info su coda complessiva
|
||||
/// </summary>
|
||||
@@ -1296,15 +1308,44 @@ namespace IOB_WIN_FORM
|
||||
|
||||
#region Private Fields
|
||||
|
||||
/// <summary>
|
||||
/// Task factory single threaded
|
||||
/// </summary>
|
||||
private static readonly TaskFactory _singleFactory = new TaskFactory(_singleScheduler);
|
||||
|
||||
/// <summary>
|
||||
/// Scheduler single threaded
|
||||
/// </summary>
|
||||
private static readonly SingleThreadTaskScheduler _singleScheduler = new SingleThreadTaskScheduler("IOB-SINGLE");
|
||||
|
||||
private readonly object _lock = new object();
|
||||
|
||||
/// <summary>
|
||||
/// Usato come semaforo x evitare doppio uso risorse threaded
|
||||
/// </summary>
|
||||
private readonly SemaphoreSlim _plcLock = new SemaphoreSlim(1, 1);
|
||||
|
||||
private CancellationTokenSource _cts;
|
||||
|
||||
/// <summary>
|
||||
/// Ritardo per errori (extra nei cicli)
|
||||
/// </summary>
|
||||
private int _errorDelay = 0;
|
||||
|
||||
// Per thread-safety
|
||||
private bool _isSuspended = false;
|
||||
|
||||
private FormWindowState _lastState = FormWindowState.Minimized;
|
||||
|
||||
private Task _workerTask;
|
||||
|
||||
/// <summary>
|
||||
/// Booleana per determinare se eseguire le chiamate DoExecTasksAsync su single thread (es FANUC) o dinamico (default)
|
||||
/// </summary>
|
||||
private bool doExeSingleThread = false;
|
||||
|
||||
private bool stopForced = false;
|
||||
|
||||
/// <summary>
|
||||
/// Contatore chiamate timers x debug timing
|
||||
/// </summary>
|
||||
@@ -1373,7 +1414,7 @@ namespace IOB_WIN_FORM
|
||||
if (IOBConfFull == null || !utils.CRB("autoLoadConf"))
|
||||
{
|
||||
IOBConfFull = new IobConfTree();
|
||||
loadIobType();
|
||||
await loadIobType();
|
||||
displayTaskAndLog("Waiting for config file selection");
|
||||
}
|
||||
|
||||
@@ -1424,11 +1465,13 @@ namespace IOB_WIN_FORM
|
||||
lgError($"AdapterForm: EXCEPTION in fase di chiamata URL di reboot:{iobObj.urlReboot}{Environment.NewLine}{exc}");
|
||||
}
|
||||
|
||||
#if false
|
||||
// avvio timer secondario x esecuzione (periodo di base: VHF!!!)
|
||||
StartWorker();
|
||||
#endif
|
||||
displayTaskAndLog($"Main workerTimer set: {IOBConfFull.General.Timers.MsVHF}ms", true);
|
||||
}
|
||||
displayTaskAndLog("Main Form OK", true);
|
||||
displayTaskAndLog("Adapter Form OK", true);
|
||||
}
|
||||
|
||||
private void btnForceAutoOdl_Click(object sender, EventArgs e)
|
||||
@@ -1512,8 +1555,10 @@ namespace IOB_WIN_FORM
|
||||
/// <summary>
|
||||
/// Verifica scadenza task
|
||||
/// </summary>
|
||||
/// <param name="ciclo"></param>
|
||||
private async Task checkScad()
|
||||
/// <param name="enabPool">Indica se siano abilitate operazioni Pool (Thread Safe)</param>
|
||||
/// <param name="enabSTID">Indica se siano abilitate le operazioni Single Thread</param>
|
||||
/// <returns></returns>
|
||||
private async Task checkScad(bool enabPool, bool enabSTID)
|
||||
{
|
||||
DateTime adesso = DateTime.Now;
|
||||
bool sendDone = false;
|
||||
@@ -1532,10 +1577,13 @@ namespace IOB_WIN_FORM
|
||||
{
|
||||
TimersCycleCount[item]++;
|
||||
Stopwatch sw = Stopwatch.StartNew();
|
||||
await iobObj.getAndSendAsync(item);
|
||||
|
||||
// chiamata di processing x frequenza
|
||||
await iobObj.getAndSendAsync(item, enabPool, enabSTID);
|
||||
|
||||
sw.Stop();
|
||||
sendDone = true;
|
||||
// metto una piccola attesa se ho altre scadenze
|
||||
TimersCycleElaps[item] += sw.Elapsed.TotalMilliseconds;
|
||||
// metto nuova scadenza perturbata 10%
|
||||
TimersVeto[item] = adesso.AddMilliseconds(iobObj.IOBConfFull.TimerMs(item, 0.1));
|
||||
@@ -1592,42 +1640,68 @@ namespace IOB_WIN_FORM
|
||||
/// <summary>
|
||||
/// Metodo principale esecuzione task in thread background (no interferenza con UI) x processi IO bound
|
||||
/// </summary>
|
||||
private async Task DoExecTasks()
|
||||
/// <param name="reqSingle">Richiesta esecuzone su single thread (es FANUC)</param>
|
||||
/// <returns></returns>
|
||||
private async Task DoExecTasksAsync(bool reqSingle)
|
||||
{
|
||||
bool doLog = false;
|
||||
// procedo!
|
||||
if (iobObj.periodicLog)
|
||||
{
|
||||
doLog = true;
|
||||
}
|
||||
// Attende il proprio turno. Se un task è già in corso, questo aspetta.
|
||||
await _plcLock.WaitAsync();
|
||||
bool doLog = iobObj.periodicLog;
|
||||
try
|
||||
{
|
||||
// check esecuzione SendTask (MsVHF) COMUNQUE...
|
||||
await iobObj.getAndSendAsync(gatherCycle.VHF);
|
||||
// imposto variabili x esecuzione separata task Single Thread / Pooled Thread
|
||||
bool reqSTE = iobObj.IOBConfFull.General.ExeSingleThread;
|
||||
bool enabSTID = reqSTE ? reqSingle : true;
|
||||
bool enabPool = !reqSTE;
|
||||
|
||||
if (enabPool)
|
||||
{
|
||||
// check esecuzione SendTask (MsVHF) COMUNQUE...
|
||||
await iobObj.getAndSendAsync(gatherCycle.VHF, enabPool, enabSTID);
|
||||
}
|
||||
// eseguo cicli attivi SOLO se adapter è in EFFETTIVO running...
|
||||
if (iobObj.adpRunning)
|
||||
{
|
||||
if (iobObj.connectionOk)
|
||||
{
|
||||
// se richiesto faccio memory DUMP INIZIALE!
|
||||
if (iobObj.doStartMemDump)
|
||||
DateTime adesso = DateTime.Now;
|
||||
// verifico non ci sia veto comunicazioni lettura...
|
||||
if (iobObj.queueInEnabCurr)
|
||||
{
|
||||
lgInfo("Inizio dump memoria");
|
||||
iobObj.saveMemDump(dumpType.STARTUP);
|
||||
// fatto! non ripeto...
|
||||
iobObj.doStartMemDump = false;
|
||||
lgInfo("Finito dump memoria");
|
||||
if (enabSTID)
|
||||
{
|
||||
// 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");
|
||||
}
|
||||
}
|
||||
if (enabPool)
|
||||
{
|
||||
// controllo se sia abilitato sampleDump della meoria (periodico)
|
||||
if (iobObj.doSampleMemory)
|
||||
{
|
||||
checkSampleMem();
|
||||
}
|
||||
}
|
||||
|
||||
// MAIN: controllo TUTTE le scadenze...
|
||||
await checkScad(enabPool, enabSTID);
|
||||
|
||||
// wait opzionale in coda
|
||||
if (utils.CRI("waitEndCycle") > 0)
|
||||
{
|
||||
await Task.Delay(utils.CRI("waitEndCycle"));
|
||||
}
|
||||
}
|
||||
// controllo se sia abilitato sampleDump della meoria (periodico)
|
||||
if (iobObj.doSampleMemory)
|
||||
else
|
||||
{
|
||||
checkSampleMem();
|
||||
}
|
||||
// controllo TUTTE le scadenze...
|
||||
checkScad();
|
||||
if (utils.CRI("waitEndCycle") > 0)
|
||||
{
|
||||
await Task.Delay(utils.CRI("waitEndCycle"));
|
||||
lgTrace($"VETO queueInEnabCurr | veto attivo | {adesso:yyyy.MM.dd HH:mm:ss}");
|
||||
iobObj.checkVetoQueueIn();
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -1663,7 +1737,11 @@ namespace IOB_WIN_FORM
|
||||
}
|
||||
catch (Exception exc)
|
||||
{
|
||||
lgError(string.Format("Eccezione in fase di gatherTick: {0}{1}", Environment.NewLine, exc));
|
||||
lgError($"Eccezione in fase di DoExecTasksAsync: {Environment.NewLine}{exc}");
|
||||
}
|
||||
finally
|
||||
{
|
||||
_plcLock.Release();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1706,8 +1784,6 @@ namespace IOB_WIN_FORM
|
||||
lgError($"Errore in fermaTutto |stopTimer: {stopTimer} | tryRestart: {tryRestart} | forceDequeue: {forceDequeue} | updateForm: {updateForm}{Environment.NewLine}{ex.Message}");
|
||||
}
|
||||
|
||||
|
||||
|
||||
newDisplayData currDispData = new newDisplayData();
|
||||
currDispData.semIn = Semaforo.SS;
|
||||
currDispData.semOut = Semaforo.SS;
|
||||
@@ -1812,7 +1888,7 @@ namespace IOB_WIN_FORM
|
||||
IOBConfFull.SaveYaml(fullPath.Replace("iob", "yaml"));
|
||||
|
||||
// carico IOB
|
||||
loadIobType();
|
||||
_ = loadIobType();
|
||||
// invio file di conf!
|
||||
IOBConfFull.SendConfYaml(iobObj.urlSaveConfYaml);
|
||||
|
||||
@@ -1859,7 +1935,7 @@ namespace IOB_WIN_FORM
|
||||
}
|
||||
var appVers = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version;
|
||||
|
||||
loadIobType();
|
||||
_ = loadIobType();
|
||||
// avvio macchina con adapter specificato...
|
||||
if (utils.CRB("autoStartOnLoad"))
|
||||
{
|
||||
@@ -1922,7 +1998,6 @@ namespace IOB_WIN_FORM
|
||||
_lastState = this.WindowState;
|
||||
}
|
||||
|
||||
private FormWindowState _lastState = FormWindowState.Minimized;
|
||||
/// <summary>
|
||||
/// Mostrata form
|
||||
/// </summary>
|
||||
@@ -2117,6 +2192,25 @@ namespace IOB_WIN_FORM
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Indica se debba aggiornare o meno la UI perché minimizzata o meno
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private bool ShouldUpdateUI()
|
||||
{
|
||||
// 1. Controlla se la form stessa è minimizzata
|
||||
if (this.WindowState == FormWindowState.Minimized) return false;
|
||||
|
||||
// 2. Se è una MDI Child, controlla se il Padre è minimizzato
|
||||
if (this.MdiParent != null && this.MdiParent.WindowState == FormWindowState.Minimized)
|
||||
return false;
|
||||
|
||||
// 3. (Opzionale) Controlla se la form è visibile
|
||||
if (!this.Visible) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void splitContainer1_Panel1_Paint(object sender, PaintEventArgs e)
|
||||
{
|
||||
}
|
||||
@@ -2139,6 +2233,24 @@ namespace IOB_WIN_FORM
|
||||
/// </summary>
|
||||
private void StartWorker()
|
||||
{
|
||||
|
||||
// Versione 1
|
||||
#if false
|
||||
_isSuspended = false;
|
||||
_cts = new CancellationTokenSource();
|
||||
|
||||
// Usiamo TaskCreationOptions.LongRunning
|
||||
// Questo suggerisce a .NET di creare un thread dedicato invece di usare il pool
|
||||
_workerTask = Task.Factory.StartNew(
|
||||
() => WorkerLoopAsync(_cts.Token),
|
||||
_cts.Token,
|
||||
TaskCreationOptions.LongRunning,
|
||||
TaskScheduler.Default).Unwrap(); // Unwrap è necessario perché WorkerLoopAsync è Task<Task>
|
||||
|
||||
#endif
|
||||
|
||||
// versone 2
|
||||
#if false
|
||||
// rimozione isSuspended
|
||||
_isSuspended = false;
|
||||
// per prima cosa disattivo il disabled...
|
||||
@@ -2153,10 +2265,170 @@ namespace IOB_WIN_FORM
|
||||
|
||||
_cts = new CancellationTokenSource();
|
||||
// Assegniamo il Task alla variabile per poterne monitorare lo stato
|
||||
if (doExeSingleThread)
|
||||
{
|
||||
// Facciamo partire tutto il loop sul thread dedicato fin dall'inizio
|
||||
_workerTask = _singleFactory.StartNew(
|
||||
() => WorkerLoopAsync(_cts.Token),
|
||||
_cts.Token
|
||||
).Unwrap();
|
||||
}
|
||||
else
|
||||
{
|
||||
_workerTask = Task.Run(() => WorkerLoopAsync(_cts.Token));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// versione 3
|
||||
#if false
|
||||
if (doExeSingleThread)
|
||||
{
|
||||
_isSuspended = false;
|
||||
_cts = new CancellationTokenSource();
|
||||
|
||||
// Creiamo un thread VERO, uno solo, che non morirà mai
|
||||
Thread dedicatedThread = new Thread(() =>
|
||||
{
|
||||
lgInfo($"[THREAD FISSO: {Thread.CurrentThread.ManagedThreadId}] Avviato");
|
||||
|
||||
while (!_cts.Token.IsCancellationRequested)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!_isSuspended)
|
||||
{
|
||||
// Eseguiamo il task asincrono in modo "bloccante" per questo thread
|
||||
// Ma essendo un thread separato, la UI non se ne accorge!
|
||||
DoExecTasksAsync().GetAwaiter().GetResult();
|
||||
}
|
||||
|
||||
// Calcolo del delay dinamico tra standard e suspended da Timers.MsVHF
|
||||
int currentDelay = _isSuspended ? 10 * IOBConfFull.General.Timers.MsVHF : IOBConfFull.General.Timers.MsVHF;
|
||||
if (_errorDelay > 0) currentDelay += _errorDelay;
|
||||
|
||||
// Dorme senza rilasciare il thread al pool
|
||||
Thread.Sleep(currentDelay);
|
||||
|
||||
// Logga l'ID: vedrai che ora torna sempre lo stesso!
|
||||
lgTrace($"[Thread: {Thread.CurrentThread.ManagedThreadId}] Fine ciclo delay");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
lgError("Errore nel loop: " + ex.Message);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
dedicatedThread.IsBackground = true;
|
||||
dedicatedThread.Name = "SingleDedicatedThread";
|
||||
dedicatedThread.Start();
|
||||
}
|
||||
else
|
||||
{
|
||||
// rimozione isSuspended
|
||||
_isSuspended = false;
|
||||
// per prima cosa disattivo il disabled...
|
||||
lock (_lock)
|
||||
{
|
||||
// 1. Controllo se è già in esecuzione
|
||||
if (_workerTask != null && !_workerTask.IsCompleted)
|
||||
{
|
||||
lgTrace("Worker già in esecuzione. Richiesta ignorata.");
|
||||
return;
|
||||
}
|
||||
|
||||
_cts = new CancellationTokenSource();
|
||||
_workerTask = Task.Run(() => WorkerLoopAsync(_cts.Token));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// versione 4
|
||||
|
||||
if (doExeSingleThread)
|
||||
{
|
||||
lock (_threadLock)
|
||||
{
|
||||
// 1. Ferma eventuali worker precedenti
|
||||
if (_cts != null)
|
||||
{
|
||||
_cts.Cancel();
|
||||
}
|
||||
|
||||
// 2. Attendi che il thread precedente sia effettivamente uscito
|
||||
if (_dedicatedThread != null && _dedicatedThread.IsAlive)
|
||||
{
|
||||
// Timeout breve per non freezare la UI, ma necessario per pulizia
|
||||
_dedicatedThread.Join(500);
|
||||
}
|
||||
|
||||
_isSuspended = false;
|
||||
_cts = new CancellationTokenSource();
|
||||
|
||||
// 3. Crea un thread NUOVO e DEDICATO
|
||||
_dedicatedThread = new Thread(() => WorkerLoopSingolo(_cts.Token))
|
||||
{
|
||||
IsBackground = true,
|
||||
Name = "Single_Dedicated_Thread",
|
||||
Priority = ThreadPriority.AboveNormal // Opzionale: dà precedenza ai dati PLC
|
||||
};
|
||||
|
||||
_dedicatedThread.Start();
|
||||
lgInfo("--- WORKER FISICO AVVIATO ---");
|
||||
}
|
||||
}
|
||||
#if false
|
||||
else
|
||||
{
|
||||
// rimozione isSuspended
|
||||
_isSuspended = false;
|
||||
// per prima cosa disattivo il disabled...
|
||||
lock (_lock)
|
||||
{
|
||||
// 1. Controllo se è già in esecuzione
|
||||
if (_workerTask != null && !_workerTask.IsCompleted)
|
||||
{
|
||||
lgTrace("Worker già in esecuzione. Richiesta ignorata.");
|
||||
return;
|
||||
}
|
||||
|
||||
_cts = new CancellationTokenSource();
|
||||
_workerTask = Task.Run(() => WorkerLoopAsync(_cts.Token));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// avvio altro thread comunque...
|
||||
// rimozione isSuspended
|
||||
_isSuspended = false;
|
||||
// per prima cosa disattivo il disabled...
|
||||
lock (_lock)
|
||||
{
|
||||
// 1. Controllo se è già in esecuzione
|
||||
if (_workerTask != null && !_workerTask.IsCompleted)
|
||||
{
|
||||
lgTrace("Worker già in esecuzione. Richiesta ignorata.");
|
||||
return;
|
||||
}
|
||||
|
||||
_cts = new CancellationTokenSource();
|
||||
_workerTask = Task.Run(() => WorkerLoopAsync(_cts.Token));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
private Thread _dedicatedThread;
|
||||
private readonly object _threadLock = new object();
|
||||
private bool _isProcessing = false; // Flag di sicurezza aggiuntivo
|
||||
|
||||
|
||||
#if false
|
||||
private BlockingCollection<Action> _workQueue = new BlockingCollection<Action>();
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// fermata dell'adapter
|
||||
/// </summary>
|
||||
@@ -2170,8 +2442,6 @@ namespace IOB_WIN_FORM
|
||||
lgInfo("UNLOAD Adapter");
|
||||
}
|
||||
|
||||
private bool stopForced = false;
|
||||
|
||||
// Metodo per fermare tutto (es. nel Form_Closing o Dispose)
|
||||
private async Task StopWorker()
|
||||
{
|
||||
@@ -2224,8 +2494,58 @@ namespace IOB_WIN_FORM
|
||||
checkAssignSize();
|
||||
}
|
||||
|
||||
private async Task WorkerLoopAsync(CancellationToken ct)
|
||||
#if false
|
||||
/// <summary>
|
||||
/// Loop di gestione worker
|
||||
/// </summary>
|
||||
/// <param name="ct"></param>
|
||||
private void WorkerLoopDestined(CancellationToken ct)
|
||||
{
|
||||
try
|
||||
{
|
||||
lgInfo($"[Thread: {Thread.CurrentThread.ManagedThreadId}] Loop dedicato AVVIATO");
|
||||
|
||||
while (!ct.IsCancellationRequested)
|
||||
{
|
||||
if (!_isSuspended)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Eseguiamo il task asincrono e ASPETTIAMO che finisca
|
||||
// rimanendo su questo thread.
|
||||
DoExecTasksAsync().GetAwaiter().GetResult();
|
||||
|
||||
lgTrace($"[Thread: {Thread.CurrentThread.ManagedThreadId}] Task completato");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
lgError("Errore durante i task: " + ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
int currentDelay = _isSuspended ? 10 * IOBConfFull.General.Timers.MsVHF : IOBConfFull.General.Timers.MsVHF;
|
||||
if (_errorDelay > 0) currentDelay += _errorDelay;
|
||||
|
||||
// Invece di await Task.Delay, usiamo il WaitHandle del CancellationToken
|
||||
// Questo blocca il thread attuale per X millisecondi o finché non viene cancellato
|
||||
ct.WaitHandle.WaitOne(currentDelay);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
lgError("Errore fatale nel thread dedicato: " + ex.Message);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
/// <summary>
|
||||
/// Loop di gestione worker singolo
|
||||
/// </summary>
|
||||
/// <param name="ct"></param>
|
||||
private void WorkerLoopSingolo(CancellationToken ct)
|
||||
{
|
||||
int threadId = Thread.CurrentThread.ManagedThreadId;
|
||||
lgInfo($"[Thread {threadId}] Loop fisico entrato in esecuzione.");
|
||||
|
||||
try
|
||||
{
|
||||
while (!ct.IsCancellationRequested)
|
||||
@@ -2234,7 +2554,75 @@ namespace IOB_WIN_FORM
|
||||
{
|
||||
try
|
||||
{
|
||||
await DoExecTasks();
|
||||
// Eseguiamo il lavoro asincrono in modo SINCRONO su questo thread.
|
||||
// .GetAwaiter().GetResult() blocca questo thread finché il task non è finito.
|
||||
DoExecTasksAsync(true).GetAwaiter().GetResult();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
lgError($"Errore nel task: {ex.Message}");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// se non fosse stop richiesto da utente...
|
||||
if (!stopForced)
|
||||
{
|
||||
DateTime dtVeto = lastStartTry.AddMilliseconds(waitRecMSec / 2);
|
||||
// verifica scadenza controllo SE fosse offline x eseguire test riconnessione...
|
||||
if (iobObj.adpTryRestart && (DateTime.Now > dtVeto) && iobObj.adpRunning && !iobObj.connectionOk)
|
||||
{
|
||||
lgTrace($"WorkerLoopAsync sospeso: tentativo riavvio periodico");
|
||||
lastStartTry = DateTime.Now;
|
||||
iobObj.tryConnect();
|
||||
}
|
||||
else
|
||||
{
|
||||
lgTrace($"WorkerLoopAsync sospeso: NON esegue task specifici | _isSuspended: {_isSuspended}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Calcolo del delay dinamico tra standard e suspended da Timers.MsVHF
|
||||
int currentDelay = _isSuspended ? 10 * IOBConfFull.General.Timers.MsVHF : IOBConfFull.General.Timers.MsVHF;
|
||||
|
||||
// ATTESA: Non rilascia il thread al pool di .NET
|
||||
// Si interrompe subito se ct viene cancellato
|
||||
bool cancelled = ct.WaitHandle.WaitOne(currentDelay);
|
||||
if (cancelled) break;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
lgError($"FATAL: Il thread dedicato {threadId} è morto: {ex.Message}");
|
||||
}
|
||||
finally
|
||||
{
|
||||
lgInfo($"[Thread {threadId}] Loop fisico terminato.");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Loop di gestione worker
|
||||
/// </summary>
|
||||
/// <param name="ct"></param>
|
||||
/// <returns></returns>
|
||||
private async Task WorkerLoopAsync(CancellationToken ct)
|
||||
{
|
||||
try
|
||||
{
|
||||
lgTrace($"[Thread: {Thread.CurrentThread.ManagedThreadId}] Inizio loop");
|
||||
|
||||
while (!ct.IsCancellationRequested)
|
||||
{
|
||||
if (!_isSuspended)
|
||||
{
|
||||
try
|
||||
{
|
||||
int threadIdInt = Thread.CurrentThread.ManagedThreadId;
|
||||
await DoExecTasksAsync(false);
|
||||
lgTrace($"[Thread: {threadIdInt}] factory exec DoExecTasksAsync");
|
||||
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -2261,13 +2649,24 @@ namespace IOB_WIN_FORM
|
||||
}
|
||||
}
|
||||
|
||||
// Calcolo del delay dinamico da Timers.MsVHF
|
||||
// Calcolo del delay dinamico tra standard e suspended da Timers.MsVHF
|
||||
int currentDelay = _isSuspended ? 10 * IOBConfFull.General.Timers.MsVHF : IOBConfFull.General.Timers.MsVHF;
|
||||
|
||||
// Il Task.Delay accetta il CancellationToken.
|
||||
// Se chiudi l'app mentre sta "dormendo", l'attesa si interrompe IMMEDIATAMENTE
|
||||
// senza dover aspettare la fine del timer, velocizzando la chiusura.
|
||||
// se ho error delay --> log!
|
||||
if (_errorDelay > 0)
|
||||
{
|
||||
currentDelay += _errorDelay;
|
||||
lgTrace($"WorkerLoopAsync | delay: {currentDelay}");
|
||||
}
|
||||
|
||||
// 4. ATTESA INTERROMPIBILE
|
||||
// Il delay asincrono permette al sistema di riutilizzare il thread se necessario,
|
||||
// ma il 'while' garantisce che non inizieremo il prossimo DoExecTasksAsync prematuramente.
|
||||
//await Task.Delay(currentDelay, ct).ConfigureAwait(false);
|
||||
await Task.Delay(currentDelay, ct);
|
||||
|
||||
// Logga l'ID: vedrai che ora torna sempre lo stesso!
|
||||
lgTrace($"[Thread: {Thread.CurrentThread.ManagedThreadId}] Fine ciclo delay");
|
||||
}
|
||||
lgInfo("Worker interrotto per cancellation token.");
|
||||
}
|
||||
|
||||
@@ -1263,13 +1263,7 @@ namespace IOB_WIN_FORM.Iob
|
||||
return answ;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifica veto coda QueueIN ed aggiorna abilitazione su variabile
|
||||
/// </summary>
|
||||
protected void checkVetoQueueIn()
|
||||
{
|
||||
queueInEnabCurr = dtVetoQueueIN < DateTime.Now;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Conversione string row in log generico
|
||||
@@ -3222,24 +3216,7 @@ namespace IOB_WIN_FORM.Iob
|
||||
url2call = $"{urlRemTask2ExeTav(codTav)}{taskName}";
|
||||
}
|
||||
|
||||
#if false
|
||||
|
||||
try
|
||||
{
|
||||
Task.Run(async () => answ = await utils.callUrlAsync(url2call))
|
||||
.GetAwaiter()
|
||||
.GetResult();
|
||||
lgInfo($"Task2Exe.remTask2exe | {esitoTask} | chiamata URL {url2call} | answ: {answ}");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
lgError("ProcessAutoOdl | Crash nel ponte Sync/Async: " + ex.Message);
|
||||
}
|
||||
#endif
|
||||
await utils.callUrlAsync(url2call);
|
||||
#if false
|
||||
answ = utils.callUrlNow(url2call);
|
||||
#endif
|
||||
}
|
||||
return answ;
|
||||
}
|
||||
|
||||
@@ -653,12 +653,6 @@ namespace IOB_WIN_FORM.Iob
|
||||
else
|
||||
{
|
||||
currentAnsw = await ExecuteIobCheckWithRetry(maxRetries: 5);
|
||||
#if false
|
||||
// 2. Chiamata asincrona con Retry (Ponte Sync/Async)
|
||||
currentAnsw = Task.Run(async () => await ExecuteIobCheckWithRetry(maxRetries: 5))
|
||||
.GetAwaiter()
|
||||
.GetResult();
|
||||
#endif
|
||||
}
|
||||
|
||||
// 3. Gestione Stato e Logica UI
|
||||
@@ -698,14 +692,6 @@ namespace IOB_WIN_FORM.Iob
|
||||
if (dtVetoPing >= DateTime.Now) return MPOnline;
|
||||
if (DemoOut) return true;
|
||||
|
||||
#if false
|
||||
// 2. Eseguo la parte asincrona forzando l'attesa
|
||||
// Usiamo Task.Run per far girare il codice asincrono su un thread del pool
|
||||
// evitando deadlock con il thread della UI
|
||||
bool isAlive = Task.Run(async () => await ExecuteApiCheckWithRetryAsync(maxRetries: 7))
|
||||
.GetAwaiter()
|
||||
.GetResult();
|
||||
#endif
|
||||
|
||||
bool isAlive = await ExecuteApiCheckWithRetryAsync(maxRetries: 7);
|
||||
|
||||
@@ -715,6 +701,14 @@ namespace IOB_WIN_FORM.Iob
|
||||
return isAlive;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifica veto coda QueueIN ed aggiorna abilitazione su variabile
|
||||
/// </summary>
|
||||
public void checkVetoQueueIn()
|
||||
{
|
||||
queueInEnabCurr = dtVetoQueueIN < DateTime.Now;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Update visualizzaizone BIT in ingresso <paramref name="currDispData">Parametri da
|
||||
/// aggiornare x display in form</paramref>
|
||||
@@ -1248,22 +1242,28 @@ namespace IOB_WIN_FORM.Iob
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// effettua recupero dati ed invio valori modificati...
|
||||
/// Effettua recupero dati ed invio valori modificati...
|
||||
/// </summary>
|
||||
/// <param name="ciclo"></param>
|
||||
public async Task getAndSendAsync(gatherCycle ciclo)
|
||||
/// <param name="ciclo">Ciclo di freq richiesta</param>
|
||||
/// <param name="enabPool">Indica se siano abilitate operazioni Pool (Thread Safe)</param>
|
||||
/// <param name="enabSTID">Indica se siano abilitate le operazioni Single Thread</param>
|
||||
/// <returns></returns>
|
||||
public async Task getAndSendAsync(gatherCycle ciclo, bool enabPool, bool enabSTID)
|
||||
{
|
||||
// init obj display
|
||||
newDisplayData currDispData = new newDisplayData();
|
||||
// IN OGNI CASO a prima di tutto EFFETTUO GESTIONE INVII dati da code!!!
|
||||
try
|
||||
if (enabPool)
|
||||
{
|
||||
await TrySendValuesAsync();
|
||||
}
|
||||
catch (Exception exc)
|
||||
{
|
||||
lgError(exc, "Errore in gestione svuotamento/invio preliminare code memoria");
|
||||
currDispData.semOut = Semaforo.SR;
|
||||
// IN OGNI CASO a prima di tutto EFFETTUO GESTIONE INVII dati da code!!!
|
||||
try
|
||||
{
|
||||
await TrySendValuesAsync();
|
||||
}
|
||||
catch (Exception exc)
|
||||
{
|
||||
lgError(exc, "Errore in gestione svuotamento/invio preliminare code memoria");
|
||||
currDispData.semOut = Semaforo.SR;
|
||||
}
|
||||
}
|
||||
// controllo connessione/connettività
|
||||
if (connectionOk)
|
||||
@@ -1293,81 +1293,105 @@ namespace IOB_WIN_FORM.Iob
|
||||
bool showDebugData = false;
|
||||
if (ciclo == gatherCycle.VHF)
|
||||
{
|
||||
processVHF();
|
||||
if (enabPool)
|
||||
{
|
||||
processVHF();
|
||||
}
|
||||
}
|
||||
// processing dati memoria (lettura, filtraggio, enqueque)
|
||||
else if (ciclo == gatherCycle.HF)
|
||||
{
|
||||
processWhatchDog();
|
||||
processAllMemory();
|
||||
if (enabSTID)
|
||||
{
|
||||
processWhatchDog();
|
||||
processAllMemory();
|
||||
}
|
||||
}
|
||||
else if (ciclo == gatherCycle.MF)
|
||||
{
|
||||
processMode();
|
||||
await processServerRequests();
|
||||
processCustomTaskMF();
|
||||
processOverride();
|
||||
processContapezzi();
|
||||
processCncAlarms();
|
||||
processDynData();
|
||||
processMem2Write();
|
||||
processAllMemory();
|
||||
if (enabSTID)
|
||||
{
|
||||
processMode();
|
||||
await processServerRequests();
|
||||
processCustomTaskMF();
|
||||
processOverride();
|
||||
processContapezzi();
|
||||
processCncAlarms();
|
||||
processDynData();
|
||||
processMem2Write();
|
||||
processAllMemory();
|
||||
}
|
||||
}
|
||||
else if (ciclo == gatherCycle.LF)
|
||||
{
|
||||
processCustomTaskLF();
|
||||
await processOtherCounters();
|
||||
processProgram();
|
||||
// verifico se devo gestire cambio ODL in modo automatico
|
||||
await ProcessAutoOdlAsync();
|
||||
// verifico se devo gestire auto generazione dossier quotidiana
|
||||
ProcessAutoDossier();
|
||||
// effettua gestione import file se configurato...
|
||||
await ProcessFileImportAsync();
|
||||
// effettua process ritorno ricette
|
||||
await ProcessRecipeFileRetAsync();
|
||||
if (enabSTID)
|
||||
{
|
||||
processCustomTaskLF();
|
||||
await processOtherCounters();
|
||||
processProgram();
|
||||
}
|
||||
if (enabPool)
|
||||
{
|
||||
// verifico se devo gestire cambio ODL in modo automatico
|
||||
await ProcessAutoOdlAsync();
|
||||
// verifico se devo gestire auto generazione dossier quotidiana
|
||||
ProcessAutoDossier();
|
||||
// effettua gestione import file se configurato...
|
||||
await ProcessFileImportAsync();
|
||||
// effettua process ritorno ricette
|
||||
await ProcessRecipeFileRetAsync();
|
||||
}
|
||||
}
|
||||
else if (ciclo == gatherCycle.VLF)
|
||||
{
|
||||
if (utils.CRB("enableContapezzi"))
|
||||
if (enabPool)
|
||||
{
|
||||
// rilettura contapezzi da server...
|
||||
lgTrace("Ciclo MsVLF: pzCntReload(true)");
|
||||
if (!isMulti)
|
||||
if (utils.CRB("enableContapezzi"))
|
||||
{
|
||||
pzCntReload(true);
|
||||
// rilettura contapezzi da server...
|
||||
lgTrace("Ciclo MsVLF: pzCntReload(true)");
|
||||
if (!isMulti)
|
||||
{
|
||||
pzCntReload(true);
|
||||
}
|
||||
// refresh associazione Macchina - IOB
|
||||
await SendM2IobAsync();
|
||||
// invio altri dati accessori...
|
||||
await SendMachineConfAsync();
|
||||
}
|
||||
// refresh associazione Macchina - IOB
|
||||
await SendM2IobAsync();
|
||||
// invio altri dati accessori...
|
||||
await SendMachineConfAsync();
|
||||
}
|
||||
// recupero dati SETUP (sysinfo) e li invio/mostro se variati...
|
||||
processSysInfo();
|
||||
// checkLogDir x shrink!
|
||||
checkShrinkDir();
|
||||
// eventuale log!
|
||||
if (utils.CRB("recTime"))
|
||||
{
|
||||
try
|
||||
// checkLogDir x shrink!
|
||||
checkShrinkDir();
|
||||
// eventuale log!
|
||||
if (utils.CRB("recTime"))
|
||||
{
|
||||
logTimeResults();
|
||||
try
|
||||
{
|
||||
logTimeResults();
|
||||
}
|
||||
catch
|
||||
{ }
|
||||
}
|
||||
catch
|
||||
{ }
|
||||
processRecipeSyncArch();
|
||||
}
|
||||
processRecipeSyncArch();
|
||||
if (enableSlowData)
|
||||
if (enabSTID)
|
||||
{
|
||||
processSlowDataRead();
|
||||
// recupero dati SETUP (sysinfo) e li invio/mostro se variati...
|
||||
processSysInfo();
|
||||
if (enableSlowData)
|
||||
{
|
||||
processSlowDataRead();
|
||||
}
|
||||
}
|
||||
}
|
||||
// mostra eventuali altri dati di processo...
|
||||
reportDataProc();
|
||||
if (showDebugData)
|
||||
if (enabPool)
|
||||
{
|
||||
// verifica se debba salvare e mostrare dati
|
||||
checkSavePersDataLayer();
|
||||
// mostra eventuali altri dati di processo...
|
||||
reportDataProc();
|
||||
if (showDebugData)
|
||||
{
|
||||
// verifica se debba salvare e mostrare dati
|
||||
checkSavePersDataLayer();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception exc)
|
||||
@@ -1402,21 +1426,24 @@ namespace IOB_WIN_FORM.Iob
|
||||
}
|
||||
else
|
||||
{
|
||||
// anche se NON connesso alcuni task di bassa freq li eseguo...
|
||||
if (ciclo == gatherCycle.LF)
|
||||
if (enabPool)
|
||||
{
|
||||
// verifico se devo gestire cambio ODL in modo automatico
|
||||
await ProcessAutoOdlAsync();
|
||||
// verifico se devo gestire auto generazione dossier quotidiana
|
||||
ProcessAutoDossier();
|
||||
// effettua gestione import file se configurato...
|
||||
await ProcessFileImportAsync();
|
||||
// effettua process ritorno ricette
|
||||
await ProcessRecipeFileRetAsync();
|
||||
}
|
||||
else if (ciclo == gatherCycle.VLF)
|
||||
{
|
||||
processRecipeSyncArch();
|
||||
// anche se NON connesso alcuni task di bassa freq li eseguo...
|
||||
if (ciclo == gatherCycle.LF)
|
||||
{
|
||||
// verifico se devo gestire cambio ODL in modo automatico
|
||||
await ProcessAutoOdlAsync();
|
||||
// verifico se devo gestire auto generazione dossier quotidiana
|
||||
ProcessAutoDossier();
|
||||
// effettua gestione import file se configurato...
|
||||
await ProcessFileImportAsync();
|
||||
// effettua process ritorno ricette
|
||||
await ProcessRecipeFileRetAsync();
|
||||
}
|
||||
else if (ciclo == gatherCycle.VLF)
|
||||
{
|
||||
processRecipeSyncArch();
|
||||
}
|
||||
}
|
||||
|
||||
// provo a riconnettere SE abilitato tryRestart...
|
||||
|
||||
Reference in New Issue
Block a user