LibDispatch is Apple's re-implementation of SubmitThreadpoolWork WinAPI, introduced in Windows Vista 3 years before libdispatch. Thread pools work better in Windows because OS kernel support.
In libdispatch and similar cross-platform libraries, OS kernel is unaware of the thread pool. The kernel implements individual threads and schedules them fairly, the rest of the code is user mode.
Windows has I/O completion ports (IOCP) in the kernel since forever, more specifically since NT 3.5 shipped in 1994. That newer Vista API is probably built on top, or uses same kernel features.
Here's an important part from IOCP's documentation:
> The system also allows a thread waiting in GetQueuedCompletionStatus to process a completion packet if another running thread associated with the same I/O completion port enters a wait state for other reasons, for example the SuspendThread function.
This is the unique part which can't be implemented in a user mode library. If you create a thread pool with 1 OS thread per hardware thread, and call any blocking API from the pool, a hardware thread will go to sleep. If you create a thread pool with multiple OS threads per hardware thread, the OS will use all of them concurrently and you'll get overhead from context switches, also latency spikes.
The problem can only be solved in OS kernel. That's why in Windows, thread pools usually works OK.