On Windows, the I/O completion port offers a way to use a thread pool for your multi-threaded application. Designed primarily for efficient processing of asynchronous I/O, it supports files, named pipes, sockets and device control.
In addition to that, you can post your own packets to the port. Quoting from the documentation:
The PostQueuedCompletionStatus function allows an application to queue its own special-purpose completion packets to the I/O completion port without starting an asynchronous I/O operation.An example of this is shown in the worker demo project (which uses no async I/O at all).