Skip to content

AsyncTools

Ilia Petrov-Komotskii edited this page Oct 16, 2026 · 3 revisions

Helpers for polling, wrapping callback APIs as Task, and observing completion.

using System.Threading;
using System.Threading.Tasks;
using Mane.DotNet;

await AsyncTools.WaitForCondition(
    () => File.Exists(path),
    delayMilliseconds: 50,
    timeoutMilliseconds: 5000);

WaitForCondition

Polls condition until it returns true. This is not an event: a spike that is true only between polls can be missed.

  • First check runs on the caller thread.
  • Later checks run on a thread-pool thread after ConfigureAwait(false) — do not touch Unity objects after the first await.
  • delayMilliseconds must be at least 1. Timeout can overshoot by one delay.
  • Timeout throws TimeoutException. Cancel the token for OperationCanceledException.

Callback to Task

Task load = AsyncTools.CreateTask(done => legacyLoader.Start(done));

Task<string> named = AsyncTools.CreateTask<string>(done =>
    legacyLoader.Start(result => done(result)));

CreateTask starts the callback-based operation and completes when the callback is invoked. A synchronous throw from targetMethod faults the task. Token cancel reports as OperationCanceledException. With a token that is already cancelled, targetMethod is not called at all and the task is returned cancelled.

OnComplete

Fire-and-forget observer. Uses the current SynchronizationContext (Unity main thread when present). Cancelling the token cancels the wait, not the underlying task.

download.OnComplete(ex =>
{
    if (ex != null)
        Debug.LogException(ex);
});

typedTask.OnComplete((result, ex) =>
{
    if (ex == null)
        label.text = result;
});

Success: void overload gets callback(null); Task<T> gets (result, null). Faulted: (ex) / (default, ex).

An exception thrown by the callback itself is raised like one from an async void method: on the synchronization context it ran on (on Unity's main thread it shows in the Console), otherwise on the thread pool, where a plain .NET app treats it as unhandled.

Clone this wiki locally