One of the things you can do in a coroutine is spawn a new process, with stdin etc wired up, and yield while waiting for the new process to do things. That puts a really convenient API on top of concurrent batch operations.
Coroutines give you an easy way to manage cancellation. Essentially, any yield back to the scheduler is an opportunity to inject a cancel into the task. The code run within the task doesn't need to do anything special (beyond not starving the scheduler).