A common corner-case in programming is what happens when multiple operations are attempted at the same time. One way to avoid the troubles of this corner-case is to simply prohibit having multiple operations occur simultaneously. However, it typically isn't possible to make this exclusion work in a universal fashion. Consider an object that prevents having multiple operations but permits having long-running (perhaps indefinitely long-running) operations. When faced with a long-running operation, it's desirable to have some way to prematurely stop that operation. The trick is that stopping an operation is often an operation in itself, violating the guarantee that only one operation runs at a time for at least a tiny period during shutdown of the object. This makes shutdown particularly prone to being a corner-case.
Channels don't make any guarantees about the simultaneous execution of methods, but it can still be confusing to describe their behavior during shutdown. The basic operations of accept and receive are often long-running, meaning that there frequently is going to be some overlap between these operations and the end of the channel's lifetime. The accept or receive operation needs to have some outcome when it completes. How can that outcome be determined? Here's a rule of thumb to guess the behavior of any related method for a channel. This rule of thumb can be applied for example when shutting down the system or when a session finishes all of its input.
For example, the TryReceive method returns both an object and a conditional report of success or failure. According to the rule of thumb, when the channel has no more data, it should return null for the received message. Also, it should report a conditional result of success (true, in this case) for the attempt to receive a message.
Next time: Body is a Stream