Thread pool starvation in .NET: detecting it with dotnet-counters and dotnet-stack, and fixing it

C# Async & Multithreading November 13, 2026 bash

Symptoms: latency rises sharply with load while CPU stays low, timeouts appear, and health checks fail.

bash
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
# ======================================================================
# Q: What is thread pool starvation? How do you detect and fix it?
#
# Symptoms: latency rises sharply with load while CPU stays low, timeouts
# appear, and health checks fail. Cause: threads that block (.Result,
# Thread.Sleep, sync I/O, a lock with long waits). Above the minimum, the pool
# adds new threads slowly (about 1-2 per second), so the queue keeps growing.
# Fix: async all the way. ThreadPool.SetMinThreads is a patch, not a solution.
# If a library only has a sync API, isolate it (a separate worker, a limit on
# concurrent calls).
# ======================================================================

dotnet-counters monitor -n Shop.Api --counters System.Runtime
#  ThreadPool Queue Length rising, ThreadPool Thread Count rising slowly  → starvation
dotnet-stack report -p <pid>     # where the threads are "stuck"