Start here. This is the direct spoken answer to practice first.
Why this question matters
ThreadPool starvation is often blamed whenever an API is slow. The diagnosis needs both a queueing pattern and evidence of what keeps workers unavailable.
I correlate request latency with ThreadPool thread count, queue length, completed work rate, CPU, and dependency latency. Starvation is likely when work queues grow, completion falls behind, and the pool keeps adding threads while CPU still has room. I then capture repeated managed stack snapshots during the bad interval. If many workers repeatedly sit in .Result, .Wait, synchronous I/O, lock acquisition, or another blocking path, the stacks explain why threads are unavailable. For intermittent blocking, I collect a bounded trace with ThreadPool and wait events so I can see when workers block, how long they wait, and which call path caused it. That separates starvation from an overloaded downstream service, pure CPU saturation, or normal temporary thread injection.