Await

Waits for work which finishes later and returns what it produced.

This function is exported by the KS module.

Value := Await(Value , Timeout)

Parameters

Value

Type: Task, Clr task or an awaitable object

The work to wait for. A script object may expose work through a zero-argument __Await() method. Anything which does not finish later raises a TypeError.

A RealThread raises that TypeError too, because a worker has two completions: await worker.Task for what the entry function produced, or worker.Terminated for the thread being gone.

Timeout

Type: Integer

If omitted, it waits indefinitely. Otherwise, the number of milliseconds to wait before raising a TimeoutError. A timeout stops only this wait and does not cancel the work. Task.Wait is the non-throwing form.

Return Value

Type: Any

The value the work produced, or an empty string if it produced none.

Errors

A task's failure is rethrown as a catchable Keysharp error, so try around an Await works as it would around an ordinary call. It is the same Error object exposed by Task.Error. Canceled work raises a base Error.

A TimeoutError is raised if Timeout elapses first, and a TypeError if Value is not work which finishes later or its __Await() method returns a non-awaitable value.

Two waits which could never finish raise TargetError: awaiting A_RealThread.Task from inside the body which settles it, and awaiting a Post aimed at the calling thread's own real thread while the current script thread is Critical.

Remarks

Unlike C#'s await, Await does not suspend the calling function: it blocks the calling thread and processes events meanwhile, as Sleep does, so timers, hotkeys and the GUI stay responsive.

Warning: Because it processes events, Await is an interruption point: another script thread can start while it waits, just as inside Sleep. Unlike Sleep, it does not look like one — Await(f()) reads as an ordinary expression. A thread which starts during the wait can re-enter and release a Lock the waiting thread holds. Use Critical to hold a section closed across a wait.

Examples

Calling an asynchronous .NET API through #CSharp.

#Import "Ks" { Await }

#CSharp
using System.IO;
using System.Threading.Tasks;

[Export] public static async Task<object> ReadText(string path)
    => await File.ReadAllTextAsync(path);
#EndCSharp

text := Await(ReadText(A_ScriptFullPath))
MsgBox StrLen(text) " characters"

The script stays responsive while it waits.

#Import "Ks" { Task, Clr, Await }

ticks := 0
SetTimer Tick, 100

http := Clr.System.Net.Http.HttpClient()
body := Await(http.GetStringAsync("https://example.com"))

SetTimer Tick, 0
MsgBox "downloaded " StrLen(body) " characters; the timer ran " ticks " times"

Tick() {
    global ticks += 1
}

Giving up after a deadline.

#Import "Ks" { Task, Clr, Await }

http := Clr.System.Net.Http.HttpClient()
try
    body := Await(http.GetStringAsync("https://example.com"), 2000)
catch TimeoutError
    MsgBox "the server took too long"

Task, RealThread, Clr, #CSharp, Sleep, Threads