CryptoHives.Foundation.Threading.Analyzers 0.6.21

dotnet add package CryptoHives.Foundation.Threading.Analyzers --version 0.6.21
                    
NuGet\Install-Package CryptoHives.Foundation.Threading.Analyzers -Version 0.6.21
                    
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="CryptoHives.Foundation.Threading.Analyzers" Version="0.6.21">
  <PrivateAssets>all</PrivateAssets>
  <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="CryptoHives.Foundation.Threading.Analyzers" Version="0.6.21" />
                    
Directory.Packages.props
<PackageReference Include="CryptoHives.Foundation.Threading.Analyzers">
  <PrivateAssets>all</PrivateAssets>
  <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
                    
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 CryptoHives.Foundation.Threading.Analyzers --version 0.6.21
                    
#r "nuget: CryptoHives.Foundation.Threading.Analyzers, 0.6.21"
                    
#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 CryptoHives.Foundation.Threading.Analyzers@0.6.21
                    
#: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=CryptoHives.Foundation.Threading.Analyzers&version=0.6.21
                    
Install as a Cake Addin
#tool nuget:?package=CryptoHives.Foundation.Threading.Analyzers&version=0.6.21
                    
Install as a Cake Tool

CryptoHives Open Source Initiative 🐝

An open, community-driven collection of cryptography and performance libraries for the .NET ecosystem, maintained by The Keepers of the CryptoHives.


CryptoHives.Foundation.Threading.Analyzers

NuGet

Roslyn analyzers that catch common ValueTask misuse at compile time — the kind of subtle bugs, undefined behavior, and performance pitfalls that tend to show up when working with ValueTask and pooled async primitives.

Note: These analyzers are no longer bundled automatically with the CryptoHives.Foundation.Threading package. Install this package separately if you want the analyzers alongside the Threading library.


Installation

dotnet add package CryptoHives.Foundation.Threading.Analyzers

Or as a development-only dependency (no runtime reference):

<PackageReference Include="CryptoHives.Foundation.Threading.Analyzers"
                  Version="*"
                  PrivateAssets="all" />

Diagnostic Rules

ID Severity Description
CHT001 Error ValueTask awaited multiple times
CHT002 Warning ValueTask.GetAwaiter().GetResult() used (blocking)
CHT003 Warning ValueTask stored in a field
CHT004 Error ValueTask.AsTask() called multiple times
CHT005 Warning ValueTask.Result accessed directly
CHT006 Warning ValueTask passed to a potentially unsafe method
CHT007 Info AsTask() stored before signaling (causes a performance hit)
CHT008 Warning ValueTask not awaited or consumed
CHT009 Info SemaphoreSlim(1, 1) used as an async lock; consider AsyncLock instead
CHT010 Error ValueTask captured in a lambda/closure

Anti-Patterns Detected

// CHT001: Multiple await — Error
ValueTask vt = GetValueTask();
await vt;
await vt; // Error: already consumed

// CHT002: Blocking call — Warning
ValueTask vt = GetValueTask();
vt.GetAwaiter().GetResult(); // Warning: undefined behavior

// CHT003: Stored in field — Warning
private ValueTask _task; // Warning: may be consumed multiple times

// CHT004: Multiple AsTask() — Error
ValueTask vt = GetValueTask();
var t1 = vt.AsTask();
var t2 = vt.AsTask(); // Error: already consumed

// CHT005: Direct .Result — Warning
ValueTask<int> vt = GetValueTask();
int result = vt.Result; // Warning: undefined behavior

// CHT006: Passed to unsafe method — Warning
await Task.WhenAll(GetValueTask()); // Warning: use AsTask() or Preserve()

// CHT007: AsTask() before signaling — Info (performance)
Task t = someAsyncLock.LockAsync().AsTask();
// ... other work ...
await t; // Info: storing AsTask() before signal causes 10–100x slowdown

// CHT008: Unconsumed — Warning
GetValueTask(); // Warning: result not awaited or discarded

// CHT009: SemaphoreSlim(1, 1) as async lock — Info
private readonly SemaphoreSlim _lock = new SemaphoreSlim(1, 1); // Info: consider AsyncLock

Correct Patterns

// Single await — correct
await GetValueTask();

// Store, then single await — correct
ValueTask vt = GetValueTask();
await vt;

// Preserve() for safe multiple consumption
ValueTask preserved = GetValueTask().Preserve();
await preserved;
await preserved; // Safe — Preserve() wraps in a reusable Task

// AsTask() once, reuse the Task
Task t = GetValueTask().AsTask();
await t;
await t; // Task can be awaited multiple times

// Pass to WhenAll via AsTask()
await Task.WhenAll(
    GetValueTask().AsTask(),
    GetValueTask().AsTask());

// Explicit discard
_ = GetValueTask();

Automatic Code Fixes

Most diagnostics come with a code fix:

Diagnostic Available Fixes
CHT001 Convert to AsTask() at declaration; use Preserve()
CHT002 Convert to await; use AsTask() before GetAwaiter().GetResult()
CHT003 Change field type to Task
CHT004 Store AsTask() result in a variable
CHT005 Convert to await; use AsTask().Result
CHT007 Await the ValueTask directly
CHT008 Add await; discard explicitly with _ =
CHT009 Replace SemaphoreSlim(1,1) with AsyncLock
CHT010 Convert to AsTask() at declaration; use Preserve()

Configuration

Adjust rule severity in .editorconfig:

# Promote CHT007 from info to warning
dotnet_diagnostic.CHT007.severity = warning

# Disable CHT003 entirely
dotnet_diagnostic.CHT003.severity = none

Or suppress inline when it's genuinely intentional:

#pragma warning disable CHT002
valueTask.GetAwaiter().GetResult(); // intentional blocking call
#pragma warning restore CHT002

Documentation

Resource Link
Full package documentation cryptohives.github.io/Foundation/packages/threading.analyzers
Threading package cryptohives.github.io/Foundation/packages/threading
Source repository github.com/CryptoHives/Foundation

Security Policy

If you discover a vulnerability, please don't open a public issue — follow the process on the CryptoHives Security Page instead.


License

MIT — © 2026 The Keepers of the CryptoHives

There are no supported framework assets in this package.

Learn more about Target Frameworks and .NET Standard.

This package has 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.

Version Downloads Last Updated
0.6.21 63 7/4/2026
0.5.34-preview 172 6/2/2026
0.5.21-preview 119 5/2/2026
0.5.13-preview 152 4/2/2026
0.4.21-preview 175 3/1/2026
0.4.11-preview 116 2/14/2026
0.3.19-preview 153 1/26/2026
0.2.43-preview 159 1/9/2026
0.2.33-preview 465 12/9/2025
0.2.30-preview 342 12/8/2025
0.2.28-preview 294 12/7/2025