diff --git a/AgroBase/AgroBase/Models/AsyncTaskTimerModel.cs b/AgroBase/AgroBase/Models/AsyncTaskTimerModel.cs
index a8e38784d..a33b34f0f 100644
--- a/AgroBase/AgroBase/Models/AsyncTaskTimerModel.cs
+++ b/AgroBase/AgroBase/Models/AsyncTaskTimerModel.cs
@@ -20,6 +20,9 @@ namespace AgroBase.Models
private string _id;
public string Id { get { return _id; } }
private Control _uiControl;
+ private int _timeout = 60000;
+
+ private DateTime lastTick = DateTime.MinValue;
private bool DebugMessages = true;
@@ -29,16 +32,18 @@ namespace AgroBase.Models
/// A tarefa assíncrona que será executada periodicamente.
/// Intervalo em milissegundos entre as execuções.
/// Controle para executar tarefas relacionadas à UI. Opcional.
- public AsyncTaskTimerModel(string id, Func taskToExecute, int interval, Control uiControl = null)
+ public AsyncTaskTimerModel(string id, Func taskToExecute, int interval, Control uiControl = null, int timeout = 60000)
{
if (string.IsNullOrEmpty(id)) throw new ArgumentNullException(nameof(id));
if (taskToExecute == null) throw new ArgumentNullException(nameof(taskToExecute));
if (interval <= 0) throw new ArgumentException("Interval must be greater than zero.", nameof(interval));
+ if (timeout <= 0) throw new ArgumentException("Timeout must be greater than zero.", nameof(timeout));
_id = id;
_stackTrace = ObterIdDoChamador();
_taskToExecute = taskToExecute;
_interval = interval;
+ _timeout = timeout;
_uiControl = uiControl;
Timers.Add(this);
@@ -110,28 +115,50 @@ namespace AgroBase.Models
///
/// Verifica se o timer está em execução.
///
- public bool IsRunning => _cancellationTokenSource != null;
+ public bool IsRunning
+ {
+ get
+ {
+ return _cancellationTokenSource != null && !_cancellationTokenSource.Token.IsCancellationRequested && lastTick.AddMilliseconds(_timeout) >= DateTime.Now;
+ }
+ }
///
- /// Loop interno do timer.
+ /// Loop interno do timer com timeout na execução da tarefa.
///
private async Task TimerLoopAsync(CancellationToken cancellationToken)
{
while (!cancellationToken.IsCancellationRequested)
{
- //ExibirConsole($"TICK");
+ lastTick = DateTime.Now;
try
{
- if (_uiControl != null)
+ // Cria um token de cancelamento específico para o timeout
+ var timeoutCts = new CancellationTokenSource();
+ var timeoutToken = timeoutCts.Token;
+
+ // Define o tempo limite para a execução da tarefa
+ timeoutCts.CancelAfter(_timeout);
+
+ var linkedTokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, timeoutToken);
+
+ // Executa a tarefa com timeout
+ var taskToRun = _uiControl != null
+ ? FuncoesGlobais.ExecutarMetodoComVerificacaoCrossThreadAsync(_uiControl, _taskToExecute)
+ : _taskToExecute();
+
+ var completedTask = await Task.WhenAny(taskToRun, Task.Delay(_timeout, linkedTokenSource.Token));
+
+ if (completedTask == taskToRun)
{
- // Se um controle de UI foi especificado, use-o para executar tarefas relacionadas à UI
- await FuncoesGlobais.ExecutarMetodoComVerificacaoCrossThreadAsync(_uiControl, _taskToExecute);
+ // A tarefa foi concluída dentro do limite
+ await taskToRun;
}
else
{
- // Caso contrário, execute a tarefa diretamente
- await _taskToExecute();
+ // Timeout atingido
+ ExibirConsole($"TIMEOUT - tarefa excedeu {_timeout}ms");
}
// Aguarda o intervalo antes da próxima execução
@@ -154,6 +181,7 @@ namespace AgroBase.Models
ExibirConsole($"ENCERRADO");
}
+
private bool _disposed = false;
public void Dispose()