> For the complete documentation index, see [llms.txt](https://docs.skail.dev/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.skail.dev/aprender/fundamentos/tempo-e-agendamento.md).

# Tempo e agendamento

Como uma function espera um tempo sem segurar nada, o que acontece se a aplicação for reiniciada durante a espera, e por que a hora atual vem de um command.

## Delay é um checkpoint com hora marcada

`await SkailTask.Delay(TimeSpan.FromHours(24))` não bloqueia thread nem mantém um timer no processo. O runtime grava um passo no histórico da execução com o prazo, pede ao skail para acordar a execução naquele momento e libera a execução: ela hiberna. Quando o prazo chega, o skail entrega a execução de novo à sua aplicação, o runtime reexecuta a function, encontra o passo do delay concluído e segue para o próximo `await`.

Há três formas de escrever o mesmo delay: `SkailTask.Delay(TimeSpan)`, `SkailTask.DelaySeconds(ulong)` e `SkailTask.DelayMinutes(ulong)`. Funcionam para segundos, minutos, horas, dias e semanas. Um `Delay` de 30 dias custa o mesmo que um de 30 segundos enquanto espera: nada.

## O que acontece durante a espera

A aplicação pode ser reiniciada, escalada, atualizada ou movida de servidor. A execução hibernada não está nela; está no skail, com o prazo marcado. Quando o prazo chega e a aplicação está rodando, a execução retoma. Se a aplicação estiver fora do ar no momento, a execução espera e é entregue quando a aplicação voltar; o delay não se perde, só a retomada atrasa.

Se o código publicado mudou durante a espera, a retomada usa o código novo. Isso funciona enquanto a sequência de `await`s da function for a mesma; se não for, o replay diverge. Ver [Versionamento de código com execuções em andamento](/aprender/fundamentos/versionamento-de-codigo-com-execucoes-em-andamento.md).

## A hora atual vem de um command

Dentro de uma function, `DateTime.UtcNow` é proibido: o valor muda entre a primeira execução e cada replay, e um cálculo de prazo feito com ele produz um delay diferente a cada vez. A forma correta é ler o relógio em um command, que executa uma vez e grava o valor:

```csharp
[SkailFunction]
public async SkailTask LembrarVencimento(Fatura fatura)
{
    var agora = await ObterDataAtual();                          // gravado; igual em todo replay
    var ateOLembrete = fatura.Vencimento.AddDays(-3) - agora;
    if (ateOLembrete > TimeSpan.Zero)
        await SkailTask.Delay(ateOLembrete);
    await EnviarLembrete(fatura.Id);
}

[SkailCommand]
public async SkailTask<DateTime> ObterDataAtual() => await Task.FromResult(DateTime.UtcNow);
```

Repare que o delay é calculado a partir de um valor gravado, então o passo do delay é sempre o mesmo no replay. Se a fatura já vence em menos de três dias, o `if` evita um delay negativo.

## Delay como prazo de uma espera

O uso mais comum do `Delay` não é esperar por esperar: é dar prazo a um `WaitForEvent`. Um `WhenAny` entre a espera e o delay decide quem venceu, e a function trata o timeout. O padrão completo está em [Como esperar com timeout](/construir/escrever-fluxos/como-esperar-com-timeout.md).

## Agendar para uma data

Não existe "execute às 8h de segunda" como primitiva. O equivalente é calcular o intervalo até a data desejada a partir de um relógio lido em command e usar `Delay`. Para rotinas recorrentes, uma function que faz o trabalho, espera até a próxima data e chama a si mesma inicia um novo ciclo; para vida longa, veja o item sobre laços em [Antipadrões](/construir/padroes-e-antipadroes/antipadroes-o-que-nao-fazer-e-por-que.md).

## Próximos passos

[Delay](/construir/sdk-.net/delay.md) é a referência das sobrecargas. [Timeout e prazo](/construir/padroes-e-antipadroes/timeout-e-prazo.md) e [Régua de lembretes](/construir/padroes-e-antipadroes/regua-de-lembretes.md) são os dois padrões que mais usam tempo. [Hibernação e retomada](/aprender/fundamentos/hibernacao-e-retomada.md) explica o que acontece com a execução enquanto o prazo não chega.
