Debugging
Debug builds
The library is compiled as part of your project, so in Debug configurations (with _DEBUG) its
assertions are enabled. They catch some violations of the
usage contract where they happen, by breaking into the
debugger — for example a second task waiting on an _s primitive, a CriticalSection left by a
task that does not own it, or a synchronization object destroyed while tasks are still suspended on
it. The core itself is the same release build in every configuration.
Release builds check nothing. Run your tests in Debug regularly, especially after changing how objects are owned or how many tasks wait on a primitive.
The Visual Studio extension
Suspended tasks are not threads, so the debugger's Threads and Call Stack windows do not show them. The ThinkMeta Concurrent Tasks extension for Visual Studio adds a tool window, similar to the built-in Tasks window, that shows while the program is paused:
- every live scheduler and its threads,
- the tasks and task contexts, including the suspended ones,
- the call stack of a suspended task: double-click it, and the Call Stack window shows where the task is waiting.
Open it with Debug › Windows › ThinkMeta Concurrent Tasks while debugging. The extension supports Visual Studio 2026.
Note
The extension is a preview. Contact us if you would like to try it.
Common mistakes
| Symptom | Likely cause |
|---|---|
| A wait never returns | Nobody signals; or an _s primitive got a second waiter; or a timeout is used without EnableTimers. |
| Access violation in the scheduler after a task finished | The task object or a primitive was destroyed too early — see Lifetimes and sizing. |
| Hang or corruption under load | A queue overflowed: taskQueueCapacity or a BoundedPointerQueue is too small. |
| All threads busy, little progress | Tasks block their threads in OS calls instead of waiting; use the asynchronous forms or move the blocking work to own threads. |
| The process ends without a message | An exception escaped Run. |