views:

481

answers:

2

I am a C# programmer, but I have a question about Async Workflows in F#. Supposing I have the following class in a C# class library:

class File {
 IAsyncResult BeginReadAll(string fileName, AsyncCallback callback, object state){}
 string EndReadAll(IAsyncResult result){}
}

My understanding is that is possible in F# for me to make a function called ReadAllAsync that I can call like this:

async {  let! rsp = ReadAllAsync() }

and that it will not block the calling thread but rather release it to the thread pool and then return on another thread when the operation finishes. I think I understand how to code this in F# using Async.Primitive, but my question is: can I call this ReadAllAsync function from C# code? If so, how do I package the F# code in a class library to access from C#?

+2  A: 

Here's an article that shows exactly what you're asking for:

http://codebetter.com/blogs/matthew.podwysocki/archive/2008/10/15/functional-c-implementing-async-computations-in-c.aspx

However, you end up using C#'s monad syntax. Since LINQ was designed for querying, it looks a bit odd. Additionally, there's no support for try/catch or using for dispose.

The "ReadAllAsync" that you get from Async.BuildPrimitive isn't going to have the same magic without the right monad syntax. Calling it is straightforward enough, but the real utility is being able to compose it.

You're probably better off just using the C# style, unfortunately,

MichaelGG
+2  A: 

Happily, when Beta2 arrives, the F# core library will have this method in the Async module:

/// Return three functions that can be used to implement the .NET Asynchronous 
/// Programming Model (APM) for a given asynchronous computation.
/// 
/// The functions should normally be published as members with prefix 'Begin',
/// 'End' and 'Cancel', and can be used within a type definition as follows:
/// <c>
///   let beginAction,endAction,cancelAction = Async.AsBeginEnd computation
///   member x.BeginSomeOperation(callback,state) = beginAction(callback,state)
///   member x.EndSomeOperation(iar) = endAction(iar)
///   member x.CancelSomeOperation(iar) = cancelAction(iar)
/// </c>
///
/// The resulting API will be familiar to programmers in other .NET languages and 
/// is a useful way to publish asynchronous computations in .NET components.
static member AsBeginEnd : computation:Async<'T> ->                     // '
                             // The 'Begin' member
                             (System.AsyncCallback * obj -> System.IAsyncResult) * 
                             // The 'End' member
                             (System.IAsyncResult -> 'T) *              // '
                             // The 'Cancel' member
                             (System.IAsyncResult -> unit)

which will make it easy to write your async code with F# but then publish it back to C# or VB using the normal APM.

Brian