Osy#betaRun it on Osyrin: osyrin.com

Reference / Function

Wait in place (Task.Delay)

await Task.Delay(TimeSpan delay) · await Task.Delay(int millisecondsDelay) · await Task.Delay(delay, token) · var limit = 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.

stable2 examples compiled by CIfunctiontimestdlibeffect

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.

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

Signature#

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#

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)).
  • 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).)
  • 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#

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;
}
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#

Related

TimeSpan (durations)

`TimeSpan` is the duration type — a length of time, as in C#. Build one with the `TimeSpan.FromX` factories or `new…

Current time (DateTime.UtcNow, DurableClock.Now)

Read the current instant. `DateTime.UtcNow` (and the platform-idiomatic `DurableClock.Now`/…) return the current time…

async / await and Task

C#'s async and await, with C#'s meaning. A call to a Task-returning method that you do not await where you make it…

Wait for several tasks (Task.WhenAll, Task.WhenAny)

Task.WhenAll waits for every task and answers their results in order; Task.WhenAny answers the first task to finish…

Stop a task (CancellationToken) and complete one by hand (TaskCompletionSource)

C#'s cancellation, with C#'s meaning. A CancellationTokenSource hands out a Token; cancel the source and every task…

Remind (milestone reminders)

A reminder scheduled off a milestone. Its SCHEDULE is config in the header parens — `After` is the first fire (once, at…

Wall-time clocks (Accrues = false)

A timer that measures REAL time instead of SLA time. Written as a block on any clock-declaring setting — `Expire`…