Soenneker.Asyncs.Initializers
4.0.83
Prefix Reserved
See the version list below for details.
dotnet add package Soenneker.Asyncs.Initializers --version 4.0.83
NuGet\Install-Package Soenneker.Asyncs.Initializers -Version 4.0.83
<PackageReference Include="Soenneker.Asyncs.Initializers" Version="4.0.83" />
<PackageVersion Include="Soenneker.Asyncs.Initializers" Version="4.0.83" />
<PackageReference Include="Soenneker.Asyncs.Initializers" />
paket add Soenneker.Asyncs.Initializers --version 4.0.83
#r "nuget: Soenneker.Asyncs.Initializers, 4.0.83"
#:package Soenneker.Asyncs.Initializers@4.0.83
#addin nuget:?package=Soenneker.Asyncs.Initializers&version=4.0.83
#tool nuget:?package=Soenneker.Asyncs.Initializers&version=4.0.83
Soenneker.Asyncs.Initializers
One-time initialization gates for coordinating synchronous or asynchronous setup across concurrent callers.
AsyncInitializer runs a parameterless callback once. AsyncInitializer<T> passes one caller-supplied value into the callback that wins initialization. A successful initialization is published to later callers; a failed or cancelled attempt can be retried.
Installation
dotnet add package Soenneker.Asyncs.Initializers
Initialize once
Create the initializer with the work that must run once, then call Init anywhere that requires the setup to be complete:
using Soenneker.Asyncs.Initializers;
public sealed class SearchIndex
{
private readonly AsyncInitializer _initializer;
public SearchIndex()
{
_initializer = new AsyncInitializer(InitializeCore);
}
public ValueTask EnsureInitialized(
CancellationToken cancellationToken = default)
{
return _initializer.Init(cancellationToken);
}
private async ValueTask InitializeCore(
CancellationToken cancellationToken)
{
// Create mappings, warm metadata, or perform other one-time work.
await Task.Delay(10, cancellationToken);
}
}
If several callers arrive together, one executes the callback while the others wait. Once it completes successfully, later calls return immediately.
Pass initialization input
Use AsyncInitializer<T> when the one-time callback needs a value supplied at initialization time:
private readonly AsyncInitializer<string> _initializer =
new(async (connectionString, cancellationToken) =>
{
await Connect(connectionString, cancellationToken);
});
await _initializer.Init(connectionString, cancellationToken);
The value from the caller that acquires the initialization gate is used. Values supplied by concurrent callers waiting behind a successful initialization are ignored. Use a parameterless initializer over immutable constructor state when callers must not compete to choose configuration.
Supported callbacks
Both initializer types accept synchronous and asynchronous callbacks:
new AsyncInitializer(Action callback);
new AsyncInitializer(Action<CancellationToken> callback);
new AsyncInitializer(Func<ValueTask> callback);
new AsyncInitializer(Func<CancellationToken, ValueTask> callback);
The generic type provides the corresponding Action<T>, Action<T, CancellationToken>, Func<T, ValueTask>, and Func<T, CancellationToken, ValueTask> overloads.
Failure and cancellation
IsInitialized becomes true only after the callback completes successfully. If the callback throws or is cancelled:
- that caller observes the exception or cancellation;
- the initializer remains uninitialized;
- the callback is retained;
- a later caller can attempt initialization again.
A cancellation token can cancel waiting for the gate and is passed to callbacks that accept a token. Cancellation cannot undo side effects already performed by the callback.
Synchronous use
InitSync acquires the same gate as Init, so synchronous and asynchronous callers cannot run initialization simultaneously:
initializer.InitSync(cancellationToken);
When the configured callback is asynchronous, InitSync blocks until its ValueTask completes. Prefer Init in asynchronous code to avoid blocking a thread and potential synchronization-context problems.
Lifetime
After successful initialization, the callback reference is cleared so captured objects can be collected. Disposal also clears callback state and causes future Init or InitSync calls to throw ObjectDisposedException.
Disposing the initializer does not reverse initialization or dispose resources created by the callback. The owner remains responsible for those resources.
API
| Member | Behavior |
|---|---|
Init(...) |
Waits for or performs asynchronous one-time initialization. |
InitSync(...) |
Waits for or performs initialization synchronously. |
IsInitialized |
true only after successful completion. |
Dispose() / DisposeAsync() |
Closes the gate and releases captured callback references. |
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- Soenneker.Asyncs.Locks (>= 4.0.70)
- Soenneker.Atomics.ValueBools (>= 4.0.35)
- Soenneker.Extensions.ValueTask (>= 4.0.118)
NuGet packages (23)
Showing the top 5 NuGet packages that depend on Soenneker.Asyncs.Initializers:
| Package | Downloads |
|---|---|
|
Soenneker.Blazor.TomSelect
A Blazor interop library for the select user control library, Tom Select |
|
|
Soenneker.Blazor.FilePond
A Blazor interop library for the file upload library FilePond |
|
|
Soenneker.Blazor.Masonry
A lightweight, responsive Blazor component for Masonry (the cascading grid layout library) — perfect for image grids, cards, and dynamic content. |
|
|
Soenneker.TestHosts.Unit
A lightweight host for dependency-driven unit tests. |
|
|
Soenneker.Blazor.Turnstile
A Blazor interop library for Cloudflare Turnstile |
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 4.0.87 | 0 | 8/30/2026 |
| 4.0.86 | 0 | 8/30/2026 |
| 4.0.85 | 0 | 8/30/2026 |
| 4.0.84 | 205 | 8/30/2026 |
| 4.0.83 | 43 | 8/30/2026 |
| 4.0.82 | 255 | 8/29/2026 |
| 4.0.81 | 105 | 8/29/2026 |
| 4.0.80 | 36 | 8/29/2026 |
| 4.0.79 | 35 | 8/29/2026 |
| 4.0.78 | 90,522 | 8/8/2026 |
| 4.0.77 | 10,124 | 8/8/2026 |
| 4.0.76 | 41,525 | 7/29/2026 |
| 4.0.75 | 495 | 7/28/2026 |
| 4.0.74 | 403 | 7/28/2026 |
| 4.0.73 | 946 | 7/28/2026 |
| 4.0.72 | 14,655 | 7/27/2026 |
| 4.0.71 | 42,478 | 7/19/2026 |
| 4.0.70 | 7,085 | 7/18/2026 |
| 4.0.69 | 9,890 | 7/17/2026 |
| 4.0.68 | 753 | 7/17/2026 |
Update dependency Soenneker.Asyncs.Locks to 4.0.70 (#109)