Regarding the example in wikipedia: http://en.wikipedia.org/wiki/Coroutine
var q := new queue
coroutine produce
loop
while q is not full
create some new items
add the items to q
yield to consume
coroutine consume
loop
while q is not empty
remove some items from q
use the items
yield
I just wonder traditional event based approach can handle this kind of usage pattern, why need to use coroutine?
I think it is coroutines that are "traditional", and events are "modern". However, they also have different purpose; AFAIK, coroutines can either specify where to transfer control (like method calls) or be used to time-share, while events are loosely coupled communication (i.e. communicating "upwards" in a layered architecture).
Be sure to read Eric Lippert's blog series (from October, 2010) about continuation passing style if you are interested in things like these. There is one post titled "Musings about coroutines".