# Wait in place (Task.Delay)

> Wait before carrying on — between checks on a job another system is still running, before trying a call again, or for a moment in a component. `await Task.Delay(…)` pauses the code it runs in, on the server or in the browser. In a workflow body it is a DURABLE timer: the run waits, survives a restart, and carries on when the time has passed. Not awaited, it is a task, so it can race other work as a timeout; given a CancellationToken, it ends early when that is cancelled.

<!-- id: function-task-delay · area: function · stability: stable · html: https://osysharp.com/reference/function/task-delay/ -->

## Summary        {#summary}
`await Task.Delay(…)` waits, then the function carries on. Reach for it when something outside the app needs time — a
warehouse still running a statement, an API asking you to slow down — and you want to check again after a pause.

```osy syntax
while (status == "RUNNING") {
  await Task.Delay(TimeSpan.FromSeconds(2));
  status = CheckStatus(handle);
}
```

## Signature      {#signature}
```osy syntax
await Task.Delay(TimeSpan delay)
await Task.Delay(int millisecondsDelay)
await Task.Delay(delay, token)            // ends early, with TaskCanceledException, when token is cancelled
var limit = Task.Delay(TimeSpan delay);   // a Task — race it with Task.WhenAny
```

## Description    {#description}
`Task.Delay` answers a `Task`, as in C#. `await` it to wait where you are; leave the `await` off and it is a task that
finishes after the delay, which is what a timeout races against ([[function-task-whenall#timeout]]). A bare
`Task.Delay(…);` on its own line waits for nothing and is refused, naming `await`.

- **A negative delay is refused**, including C#'s `-1` ("wait forever") — a server function that never returns would
  hold its request open indefinitely.
- **Given a token, the wait ends early when it is cancelled** — with `TaskCanceledException`, which
  `catch (OperationCanceledException)` takes, exactly as in C# ([Stop a task (CancellationToken) and complete one by hand (TaskCompletionSource)](https://osysharp.com/reference/function/cancellation/)).
- **In the browser it is a timer.** A component's `await Task.Delay(300)` waits right there, in the page, and never
  sends its body to the server to be waited on.
- **In a workflow body it is a DURABLE timer.** The body's writes so far are committed, the run waits — for minutes or
  for days — and carries on from the line after the delay when the time has passed, on whichever server is running
  then. A test moves the clock with `TestClock.Advance` and lets the timer fire with `Workflow.Settle`. (A delay that
  should end a STATE rather than pause a body is still `Expire { Within = … }` — [Wall-time clocks (Accrues = false)](https://osysharp.com/reference/workflow/wall-time-clock/).)
- **An app's own `Task` keeps its name.** A to-do app's `entity Task` is still queried, constructed and passed as
  `Task`; only `Task.Delay` reaches the wait.

## Examples       {#examples}
```osy title="check a long-running job again, a little later each time" test app=function-task-delay
class Poll { public int Checks; }

// Stands in for asking another system how its job is doing: it answers RUNNING twice, then DONE.
string CheckStatus(Poll poll) {
  poll.Checks = poll.Checks + 1;
  return poll.Checks < 3 ? "RUNNING" : "DONE";
}

async Task<string> WaitForJob() {
  var poll = new Poll();
  var wait = TimeSpan.FromMilliseconds(50);
  var status = CheckStatus(poll);
  while (status == "RUNNING") {
    await Task.Delay(wait);
    wait = wait * 2;
    status = CheckStatus(poll);
  }
  return status;
}
```

```osy title="give up waiting when a token is cancelled" test app=function-task-delay
async Task<string> WaitUnlessCancelled() {
  var cts = new CancellationTokenSource(TimeSpan.FromMilliseconds(50));
  try {
    await Task.Delay(TimeSpan.FromSeconds(30), cts.Token);
    return "waited";
  } catch (OperationCanceledException) {
    return "cancelled";
  }
}
```

## See also       {#see-also}
- [TimeSpan (durations)](https://osysharp.com/reference/types/timespan/) — building the delay
- [Stop a task (CancellationToken) and complete one by hand (TaskCompletionSource)](https://osysharp.com/reference/function/cancellation/) — CancellationToken and CancellationTokenSource
- [async / await and Task](https://osysharp.com/reference/function/async-await/) — `await`, and what a task is
- [Wait for several tasks (Task.WhenAll, Task.WhenAny)](https://osysharp.com/reference/function/task-whenall/) — racing a delay as a timeout
- [Current time (DateTime.UtcNow, DurableClock.Now)](https://osysharp.com/reference/function/current-time/) — reading the clock
- [Wall-time clocks (Accrues = false)](https://osysharp.com/reference/workflow/wall-time-clock/) — a durable wait inside a workflow
- [Remind (milestone reminders)](https://osysharp.com/reference/workflow/remind/) — a durable reminder inside a workflow
