TPL Dataflow and async/await vs CCR - part 2

Dealing with asynchronous APIs will also be much easier than with CCR. First of all you can expect most (if not all) classes in the .Net framework to have another method added to them that is declared async. For example the Stream object used to have a synchronous Read method and then BeginRead and EndRead for asynchronous processing. In .Net 4.5 the Stream object also have ReadAsync which can be used to process asynchronously. If you however need to work with an API that have not been updated with an async method you can either apply the same pattern as with CCR by using TPL data-flow or you can just spawn and await two tasks like this:

  1: var asyncResult = default(IAsyncResult);
 2: var result = default(int);
 3: var mre = new ManualResetEvent(false);
 4: await Task.Run(() => 
 5:     {
 6:         stream.BeginRead(buffer, offset, count, 
 7:             r => { asyncResult = r; mre.Set(); }, null);
 8:         mre.WaitOne();
 9:     });
 10: await Task.Run(() => result = stream.EndRead(asyncResult));

You could naturally wrap this in a helper method to deal with this generically exactly the same way as with CCR.

UPDATE: First of all I was too quick to post this so there was an error in the original code. The use of BeginRead must wait on completion before completing. Second (I guess that is the price for using the latest stuff) I missed to point out that there already is a helper for making Begin/End into a task; Task.Factory.FromAsync. Last (but not least) I admit the code above is kind of stupid and yes it would block a thread pool thread. I was stuck in a pattern commonly used in CCR. Stephen Toub's first comment below show's how this should really be done using a TaskCompletionSource object. So to really learn something useful, look at that comment and the use of TaskCompletionSource.