Table of Contents

AsyncLazy<T> Class

Definition

Namespace
Bodu.Threading
Assembly
Bodu.Core.dll
Package
Bodu.Core 1.0.1
Source
AsyncLazy{T}.cs

Provides support for asynchronous lazy initialization: a value is produced at most once, on first access, and the resulting task is cached and shared by every awaiter.

public sealed class AsyncLazy<T>

Type Parameters

T

The type of the lazily produced value.

Inheritance
AsyncLazy<T>
Inherited Members
Extension Methods

Examples

private readonly AsyncLazy<Config> _config =
    new(async () => await LoadConfigAsync());

public async Task<int> GetTimeoutAsync()
{
    Config config = await _config;   // factory runs once, result is cached
    return config.TimeoutSeconds;
}

Remarks

AsyncLazy<T> is the asynchronous analogue of Lazy<T>. It wraps a Lazy<T> of Task<TResult> with ExecutionAndPublication, so the factory runs exactly once even under concurrent first access. The produced Task<TResult> is cached and may be awaited any number of times, which is why this type exposes Task<TResult> rather than a single-await ValueTask<TResult>.

When constructed from a synchronous Func<TResult>, the factory is offloaded to the thread pool via Run<TResult>(Func<TResult>) so a blocking or CPU-bound factory does not run inline on the first awaiter. A factory that throws produces a faulted task that is cached; every awaiter then observes the same exception.

The shared computation is not canceled by any single caller. Use GetValueAsync(CancellationToken) to abandon an individual wait without affecting the shared factory. A factory that attempts to obtain the value of the same instance while it is still being produced is detected and fails fast with InvalidOperationException rather than deadlocking.

Constructors

AsyncLazy(Func<Task<T>>)

Initializes a new instance of the AsyncLazy<T> class that produces its value with an asynchronous factory.

public AsyncLazy(Func<Task<T>> taskFactory)

Parameters

taskFactory Func<Task<T>>

The delegate invoked once to begin producing the value.

Exceptions

ArgumentNullException

taskFactory is null.

AsyncLazy(Func<T>)

Initializes a new instance of the AsyncLazy<T> class that produces its value with a synchronous factory offloaded to the thread pool.

public AsyncLazy(Func<T> valueFactory)

Parameters

valueFactory Func<T>

The delegate invoked once to produce the value.

Exceptions

ArgumentNullException

valueFactory is null.

Properties

IsValueCreated

Gets a value indicating whether the factory has been invoked.

public bool IsValueCreated { get; }

Property Value

bool

true if initialization has started; otherwise, false.

IsValueFactoryCompleted

Gets a value indicating whether the factory has finished producing the value (successfully or with a fault).

public bool IsValueFactoryCompleted { get; }

Property Value

bool

true if the value task has completed; otherwise, false.

Value

Gets the cached task that produces the value, invoking the factory on first access.

public Task<T> Value { get; }

Property Value

Task<T>

The shared Task<TResult> representing the lazily produced value.

Exceptions

InvalidOperationException

The value factory accessed the value of the same instance while it was being produced.

Methods

ConfigureAwait(bool)

Configures how the await on the lazily produced value is continued.

public ConfiguredTaskAwaitable<T> ConfigureAwait(bool continueOnCapturedContext)

Parameters

continueOnCapturedContext bool

true to marshal the continuation back to the captured context; otherwise, false.

Returns

ConfiguredTaskAwaitable<T>

A configured awaitable for the cached value task.

Exceptions

InvalidOperationException

The value factory accessed the value of the same instance while it was being produced.

GetAwaiter()

Gets an awaiter that resolves to the lazily produced value, enabling await on the instance directly.

public TaskAwaiter<T> GetAwaiter()

Returns

TaskAwaiter<T>

A TaskAwaiter<TResult> for the cached value task.

Exceptions

InvalidOperationException

The value factory accessed the value of the same instance while it was being produced.

GetValueAsync(CancellationToken)

Asynchronously gets the lazily produced value, abandoning only this caller's wait if the token is canceled.

public Task<T> GetValueAsync(CancellationToken cancellationToken)

Parameters

cancellationToken CancellationToken

A token used to cancel this caller's wait.

Returns

Task<T>

A Task<TResult> that completes with the shared value.

Examples

// Abandon only this caller's wait on timeout; the shared factory keeps running for others.
using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(5));
Config config = await lazy.GetValueAsync(cts.Token);

Remarks

Cancellation cancels only the returned wait; the shared initialization continues for other callers.

Exceptions

OperationCanceledException

cancellationToken was canceled before the value became available.

InvalidOperationException

The value factory accessed the value of the same instance while it was being produced.

Applies to

ProductVersions
.NET8, 10