Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Adapting .NET 4.5 async to F#

Tags:

.net-4.5

f#

The .NET 4.5 framework libraries integrate C#-style Task-based async fairly extensively. In many cases, they also continue to expose APM-style Begin/End method pairs. F# can easily adapt either method to F#-style asynchronous computations.

My question is, given an IO-bound operation that's implemented in the framework as both Begin/End and Task-based async, is there a performance or memory advantage to choosing one over the other when adapting to F# async?

For example, in .NET 4.5, System.IO.Stream has both BeginRead and ReadAsync. That means I can do this...

type System.IO.Stream with
    member x.AsyncRead(buffer, offset, count) =
        Async.FromBeginEnd(buffer, offset, count, x.BeginRead, x.EndRead)

Or I can do this...

type System.IO.Stream with
    member x.AsyncRead(buffer, offset, count) =
        x.ReadAsync(buffer, offset, count) |> Async.AwaitTask

Is there any reason to prefer one over the other? The main difference that I can think of is that the read operation will have already started when the second extension method returns, but not so with the first extension method.

like image 908
Joel Mueller Avatar asked Feb 14 '12 18:02

Joel Mueller


1 Answers

An AsyncRead extension method (implemented in terms of FromBeginEnd) is already defined in FSharp.Core. AwaitTask is just a thin wrapper over Task.ContinueWith. So it boils down to a comparison of Task and async--which is more efficient, or right for the job. Since you're working with asyncs, the only relevant difference would be performance. I'm not an expert on this, but I think async and Task address the same issue, with Task having an edge for CPU-bound operations.

EDIT

I didn't read your question carefully enough. I don't know the definitive answer, but given that Task and async are roughly equivalent, I don't see any reason to wrap a Task with an async unless it's your only option. Begin/End methods are a lower-level, more lightweight abstraction, and therefore seem like better building blocks for asyncs.

An ancillary thought: the fact that AsyncRead wasn't changed to use Task could be instructive.

like image 155
Daniel Avatar answered Nov 09 '22 04:11

Daniel