with C++ it appears as if it is basically mandatory to use ASIO
not at all. That's just a cross-platform library which gives you nice, portable code.
You can always code directly to your platform APIs (admittedly on Windows I have no idea what those are). Or, you can use std::async with futures/promises to wrap synchronous I/O (or packaged_task with your own threadpool, or whatever).
The point is there's plenty of code out there doing both asynchronous and non-blocking synchronous multiplexing I/O without using ASIO or Boost.Asio. It's just either platform-specific, or uses another 3rd-party library, or contains an equivalent amount of platform abstraction code internally.
It would be preferable not to have to rely on a third party library.
From the language point of view, your platform APIs are 3rd party. Since you definitely need to use something that isn't part of the standard library, you might just as well use the nice portable one.