Update
I asked the wrong question, rephrased (based on the great info on answers and comments):
Is there any good source on .net\'s as
I/O completion ports are a strong platform implementation detail, one that .NET cannot blindly depend on to be available. And it doesn't, it leaves it up to the CLR host to implement the glue to the operating system support for it. The underlying hosting interface is IHostIoCompletionManager, available since .NET 2.0
So if you want a hard guarantee the they actually get used then you need to get the source of the CLR host that you use. This is hard to come by, there are many and you'd need to apply to a job at Microsoft to get access to the source. Only the SSCLI20 host is available in source, it is dated and covers only the default host. Which was itself tweaked to allow the PAL to provide the I/O completion port, surely not actually present in the real CLR hosts you'd ever run on.
You were not specific about what platforms you consider. Some guesstimates:
Emphasizing that these are merely educated guesses that are not backed by proof. The question is otherwise fairly strange, it is not like you'd have an alternative if you find out that async I/O was done by overlapped I/O.
Generally, the BCL only offers async APIs if they are implemented using async IO backed by the Windows kernel. Exposing async methods that do not use async kernel-IO would be the well-known async-over-sync anti-pattern which the BCL designers are surely aware of. This would not only be useless, but harmful for performance and misleading. They don't do that.
Windows can do async IO using IOCP or using regular overlapped IO. Both are efficient, asynchronous and therefore more scalable than blocking IO.
All of this is transparent to you. Rely on async being truly async, and sync being truly sync.
If in doubt, peek under the hood with Reflector. Whenever I have done this I have found confirmed what I just stated. I have yet to see a deviating case.
What you see with Reflector is that the BCL is calling the async versions of the relevant Win32 APIs. As an example, I'll examine files and sockets:
FileStream.BeginRead
indirectly calls Win32Native.ReadFileNative
with a pointer to a NativeOverlapped
structure. The pointer is obtained by calling Overlapped.Pack
. The completion callback is stored that way. It is impossible to track how the callback is called with Reflector because that part exists in the native part of the CLR. I cannot tell whether IOCP is in use but I can tell that async IO is in use.Socket.BeginRead
indirectly calls WSARecv
. The code is quite complex. The BCL seems to be able to use overlapped IO as well as IOCP depending on the OS. The check is made in Socket.InitializeSockets
. The decision what kind of IO to use is stored in Socket.UseOverlappedIO
. If that variable is false, Socket.BindToCompletionPort
is eventually called.So for Sockets it is clearly IOCP on modern OS'es. For files I cannot tell.
I personally am not particularly interested in what kind of async IO is used as long as it is non-blocking. This is the case.