Lazywait 1.0.0
dotnet add package Lazywait --version 1.0.0
NuGet\Install-Package Lazywait -Version 1.0.0
<PackageReference Include="Lazywait" Version="1.0.0" />
<PackageVersion Include="Lazywait" Version="1.0.0" />
<PackageReference Include="Lazywait" />
paket add Lazywait --version 1.0.0
#r "nuget: Lazywait, 1.0.0"
#:package Lazywait@1.0.0
#addin nuget:?package=Lazywait&version=1.0.0
#tool nuget:?package=Lazywait&version=1.0.0
<p align="center"> <img src="resources/lazywaiter_icon.svg" alt="Lazywait" width="160" /> </p>
Lazywait
<p align="center"> <a href="https://github.com/Jhanmn/Lazywait/actions/workflows/build.yml"><img src="https://github.com/Jhanmn/Lazywait/actions/workflows/build.yml/badge.svg" alt="Build" /></a> <a href="https://www.nuget.org/packages/Lazywait"><img src="https://img.shields.io/nuget/v/Lazywait.svg" alt="NuGet" /></a> <a href="LICENSE"><img src="https://img.shields.io/github/license/Jhanmn/Lazywait.svg" alt="License" /></a> <img src="https://img.shields.io/badge/.NET-netstandard2.0-512BD4.svg" alt="Target" /> </p>
Lightweight, allocation-conscious extension methods for await-ing changes on
INotifyPropertyChanged
objects. Instead of wiring up PropertyChanged handlers by hand, you write a
single line and await until a property reaches the value you care about — with
optional timeout and cancellation support.
// Wait until the device finishes moving, or fail after 5 seconds.
await device.WaitUntil(x => x.CurrentPosition, target: 2, timeout: TimeSpan.FromSeconds(5));
Features
- Strongly-typed, expression-based API —
WaitUntil(x => x.Prop, value)gives you compile-time safety and refactor-friendly property references. - String-based API —
WhenIs("Prop", value)for cases where the property name is only known at runtime. - Synchronous fast path — if the property already equals the expected value, a completed task is returned and no event subscription is made.
- Timeout support — faults with
TimeoutExceptionif the value isn't reached in time. - Cancellation support — pass a
CancellationTokento abandon the wait. - Automatic cleanup — event handlers and registrations are released as soon as the task reaches a terminal state.
netstandard2.0— works across .NET Framework, .NET Core, and modern .NET.
Installation
Add the project to your solution, or reference the compiled assembly:
dotnet add reference path/to/src/Lazywait/Lazywait.csproj
Usage
Both methods are extension methods on any type implementing
INotifyPropertyChanged. Add the namespace:
using Lazywait;
WaitUntil — expression-based
// Wait indefinitely.
await viewModel.WaitUntil(x => x.IsLoading, false);
// Wait with a timeout.
await viewModel.WaitUntil(x => x.Status, Status.Ready, TimeSpan.FromSeconds(10));
// Wait with cancellation.
await viewModel.WaitUntil(x => x.Progress, 100, cancellationToken: token);
The selector must be a simple property-access expression (e.g. x => x.MyProp);
anything more complex throws ArgumentException.
WhenIs — string-based
await viewModel.WhenIs(nameof(ViewModelBase.Status), Status.Ready, TimeSpan.FromSeconds(10));
Useful when the property name isn't known at compile time. Throws
ArgumentException if no matching property exists on the type.
Behavior notes
- Equality is compared with
EqualityComparer<TValue>.Default. - Per the INPC convention, a
PropertyChangedevent with anullor emptyPropertyNameis treated as "any property changed" and triggers a re-check. - On timeout the returned task faults with
TimeoutException; on cancellation it transitions to the canceled state.
API reference
Task WaitUntil<TOwner, TValue>(
this TOwner owner,
Expression<Func<TOwner, TValue>> selector,
TValue expected,
TimeSpan? timeout = null,
CancellationToken cancellationToken = default)
where TOwner : INotifyPropertyChanged;
Task WhenIs<TOwner, TValue>(
this TOwner owner,
string observableName,
TValue value,
TimeSpan? timeout = null,
CancellationToken cancellationToken = default)
where TOwner : INotifyPropertyChanged;
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. 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. |
| .NET Core | netcoreapp2.0 was computed. netcoreapp2.1 was computed. netcoreapp2.2 was computed. netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
| .NET Standard | netstandard2.0 is compatible. netstandard2.1 was computed. |
| .NET Framework | net461 was computed. net462 was computed. net463 was computed. net47 was computed. net471 was computed. net472 was computed. net48 was computed. net481 was computed. |
| MonoAndroid | monoandroid was computed. |
| MonoMac | monomac was computed. |
| MonoTouch | monotouch was computed. |
| Tizen | tizen40 was computed. tizen60 was computed. |
| Xamarin.iOS | xamarinios was computed. |
| Xamarin.Mac | xamarinmac was computed. |
| Xamarin.TVOS | xamarintvos was computed. |
| Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETStandard 2.0
- No dependencies.
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.