adicionado timeout

This commit is contained in:
Diego Freitas 2024-11-25 17:06:51 -03:00
parent 69139dbb17
commit 64b79bb62b
1 changed files with 37 additions and 9 deletions

View File

@ -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
/// <param name="taskToExecute">A tarefa assíncrona que será executada periodicamente.</param>
/// <param name="interval">Intervalo em milissegundos entre as execuções.</param>
/// <param name="uiControl">Controle para executar tarefas relacionadas à UI. Opcional.</param>
public AsyncTaskTimerModel(string id, Func<Task> taskToExecute, int interval, Control uiControl = null)
public AsyncTaskTimerModel(string id, Func<Task> 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
/// <summary>
/// Verifica se o timer está em execução.
/// </summary>
public bool IsRunning => _cancellationTokenSource != null;
public bool IsRunning
{
get
{
return _cancellationTokenSource != null && !_cancellationTokenSource.Token.IsCancellationRequested && lastTick.AddMilliseconds(_timeout) >= DateTime.Now;
}
}
/// <summary>
/// Loop interno do timer.
/// Loop interno do timer com timeout na execução da tarefa.
/// </summary>
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()