I didn’t want to complicate that post by mentioning the odd history of asynchronous
PushStreamContent use, but I personally find it - er, “interesting.” :)
PushStreamContent takes an asynchronous delegate (
Func<Stream, HttpContent, TransportContext, Task>), and it finishes sending the response when that asynchronous delegate completes. This is the natural way of supporting asynchronous stream writes.
PushStreamContent was a lot weirder. It always supported asynchronous writing of the response stream, but the way it used to do so was odd, to say the least.
PushStreamContent was first introduced, it only allowed synchronous delegates (
Action<Stream, HttpContent, TransportContext>). It wasn’t really obvious, but it did actually support asynchronous usage. What you had to do was pass an asynchronous lambda expression, which would actually get converted to an
async void method. One of the main problems with
async void methods is that it’s very difficult for the caller to know when the
async void method has completed.
PushStreamContent used to solve this in an unusual way:
PushStreamContent would consider its callback “complete” when it closed the output stream. “Interesting,” indeed.
This unusual design implies an unwritten rule: after closing the output stream, the callback really shouldn’t do anything else.
PushStreamContent has been changed to support asynchronous delegates as first-class citizens (as of
Microsoft.AspNet.WebApi.Client version 5.0.0). Now it works just like any other asynchronous code, rather than having the odd “
async void that completes when the stream is closed” behavior.
There’s nothing really important in this blog post for modern code (the newer
PushStreamContent went live 3 years ago this month) - just an interesting historical note.