runtime: Make NetworkStream compatible with non-blocking I/O
The predominant way to perform I/O is async. However, in some scenarios non-blocking I/O (or polling) is better adapted - the ability to read or write as much as possible, along with a guarantee that the call would not block. This allows retaining a very deterministic, single-thread model where I/O occurs opportunistically where the application chooses, rather than launching an asynchronous operation that may occur in parallel with other processes, require synchronization etc. Note that non-blocking is quite a common pattern in Unix (but not in Windows, which may explain the lack of support in .NET).
Non-blocking I/O is currently supported at the Socket level by setting Blocking to true, and then calling Send and Receive. However, trying to construct a NetworkStream over a non-blocking socket throws an IOException (The operation is not allowed on a non-blocking Socket).
Note that .NET’s Stream.Write() returns void (unlike the Linux write system call). This probably means that the introduction of a new API element would be required to support non-blocking writing.
About this issue
- Original URL
- State: closed
- Created 7 years ago
- Comments: 40 (40 by maintainers)
It seems like we’ve had this discussion at least once before… Async I/O and non-blocking I/O really are two different things - the former is about attaching a callback to the completion, which in many cases will execute on another thread, while the latter is simply about reading/writing as much as possible, right now, without ever yielding the thread (we can call this polling). It’s not about proactor or reactor - non-blocking I/O on Unix is a socket option that alters the behavior of the read and write system calls; it’s this behavior that I’d like to have .NET support better. There may be a language issue here - when I’m saying non-blocking I/O, I’m referring to the traditional Unix way of doing I/O without blocking.
Now, if anyone wants to claim that Unix-style non-blocking I/O is useless in 2017 or has been made totally obsolete by async I/O, that’s another discussion; but before we even get into that it’s important for everyone to understand that there are two different I/O models here.