ZeroAlloc.AsyncEvents 1.1.8

dotnet add package ZeroAlloc.AsyncEvents --version 1.1.8
                    
NuGet\Install-Package ZeroAlloc.AsyncEvents -Version 1.1.8
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="ZeroAlloc.AsyncEvents" Version="1.1.8" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="ZeroAlloc.AsyncEvents" Version="1.1.8" />
                    
Directory.Packages.props
<PackageReference Include="ZeroAlloc.AsyncEvents" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add ZeroAlloc.AsyncEvents --version 1.1.8
                    
#r "nuget: ZeroAlloc.AsyncEvents, 1.1.8"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package ZeroAlloc.AsyncEvents@1.1.8
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=ZeroAlloc.AsyncEvents&version=1.1.8
                    
Install as a Cake Addin
#tool nuget:?package=ZeroAlloc.AsyncEvents&version=1.1.8
                    
Install as a Cake Tool

ZeroAlloc.AsyncEvents

NuGet Build License: MIT AOT GitHub Sponsors

Zero-allocation async event handler structs for .NET. Lock-free registration, ValueTask invocation, ArrayPool parallel dispatch.

Key Characteristics

  • Lock-free registration — CAS-loop register/unregister, no locks
  • ValueTask throughout — no Task allocations on hot paths
  • ArrayPool parallel dispatch — handlers that complete synchronously cost nothing; only unfinished or failed ones go to a rented array and WhenAll
  • Multi-target — netstandard2.0, netstandard2.1, net8.0, net10.0
  • AOT compatible

Performance

10 handlers registered, invoked once, each returning a completed task. Compared against EventHandler<T> (sync multicast, baseline) and naive async (Func<string, Task> + Task.WhenAll). BenchmarkDotNet v0.15.8, X64 RyuJIT, Intel Core i9-12900HK, in-process toolchain.

net8.0

Method Mean Error StdDev Ratio Allocated
Sync_MulticastDelegate_10Handlers 57.81 ns 1.246 ns 3.675 ns 1.00 —
NaiveAsync_TaskWhenAll_10Handlers 476.80 ns 9.552 ns 12.080 ns 8.28x 288 B
ZeroAlloc_Parallel_10Handlers 35.52 ns 1.271 ns 3.728 ns 0.62x —
ZeroAlloc_Sequential_10Handlers 47.75 ns 0.350 ns 0.328 ns 0.83x —

net10.0

Method Mean Error StdDev Ratio Allocated
Sync_MulticastDelegate_10Handlers 40.69 ns 0.501 ns 0.444 ns 1.00 —
NaiveAsync_TaskWhenAll_10Handlers 440.47 ns 20.112 ns 59.300 ns 10.83x 280 B
ZeroAlloc_Parallel_10Handlers 18.31 ns 1.093 ns 3.207 ns 0.45x —
ZeroAlloc_Sequential_10Handlers 29.60 ns 1.067 ns 3.147 ns 0.73x —

Both ZeroAlloc modes allocate nothing on either target when handlers complete synchronously, and both are faster than a sync multicast delegate. Parallel mode is more than 10× faster than naive async, which allocates 280–288 B per call.

Installation

dotnet add package ZeroAlloc.AsyncEvents

Quick Start

// Declare the backing field
private AsyncEventHandler<OrderPlacedArgs> _orderPlaced = new(InvokeMode.Parallel);

// Expose as a C# event — or use [AsyncEvent] to let the source generator do this
public event AsyncEvent<OrderPlacedArgs> OrderPlaced
{
    add    => _orderPlaced.Register(value);
    remove => _orderPlaced.Unregister(value);
}

// Invoke
await _orderPlaced.InvokeAsync(new OrderPlacedArgs(orderId), cancellationToken);

Source Generator

Annotate fields with [AsyncEvent] on a partial class and the generator writes the event property for you:

public partial class OrderService
{
    [AsyncEvent(InvokeMode.Parallel)]
    private AsyncEventHandler<OrderPlacedArgs> _orderPlaced = new(InvokeMode.Parallel);
}

Generates:

public event AsyncEvent<OrderPlacedArgs> OrderPlaced
{
    add    => _orderPlaced.Register(value);
    remove => _orderPlaced.Unregister(value);
}

Apply [AsyncEvent] to the class instead to cover all AsyncEventHandler<TArgs> fields at once. See Source Generator for details.

Async INotify* Interfaces

Async INotify* interfaces and event args are provided by ZeroAlloc.Notify, which builds on this package.

Design Philosophy

AsyncEventHandler<TArgs> is a struct wrapping a State reference — copy semantics are intentional and match how event fields work in C#. Use it as a private field and expose Register/Unregister methods, or use the +=/-= operators directly.

CancellationToken is threaded through every call site — handlers opt into cooperative cancellation at the delegate boundary. Sequential mode respects cancellation between handler invocations; parallel mode checks before dispatch.

See docs/ for full documentation.

Product 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 is compatible.  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 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. 
.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 is compatible. 
.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. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (17)

Showing the top 5 NuGet packages that depend on ZeroAlloc.AsyncEvents:

Package Downloads
AdoNet.Async.DataSet

Async DataSet and DataTable for ADO.NET (System.Data). Includes AsyncDataTable, AsyncDataSet, and AsyncDataAdapter.

AI.Sentinel

Security monitoring middleware for IChatClient — prompt injection, hallucination, and operational anomaly detection with an intervention engine.

Thalos.NET

Thalos.NET agent runtime on Microsoft Agent Framework: agent factory, tool catalog with authorization, session state machine, in-memory session store.

BlazorNative.Core

Core contracts for BlazorNative: shell bridge and interop abstractions, the INavigationManager contract, and the DI-facing primitives shared by the renderer, HTTP bridge, and component library.

BlazorNative.Renderer

The BlazorNative renderer: drives Blazor's RenderTree diffing into a native widget tree and emits binary UI patch frames for platform shells. NativeAOT/trim-compatible.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.1.8 0 10/11/2026
1.1.7 4,693 9/30/2026
1.1.6 3,114 9/28/2026
1.1.5 1,135 9/27/2026
1.1.4 11,179 9/20/2026
1.1.3 3,247 9/19/2026
1.1.2 19,164 5/28/2026
1.1.1 921 5/12/2026
1.1.0 804 5/1/2026
1.0.3 1,436 5/1/2026
1.0.2 1,130 4/29/2026
1.0.1 1,145 4/28/2026
1.0.0 1,423 3/27/2026
0.3.0 139 4/1/2026
0.2.1 288 3/27/2026