Consuming F# Async from C# - f#

Suppose that I have the following code:
namespace Library1
open System.Threading.Tasks
open System.Threading
open System.Runtime.Remoting.Messaging
open System
type public Class1() =
let printThread (message) =
printfn "%s %A" message Thread.CurrentThread.ManagedThreadId
let bar =
printThread ("first bar")
async {
printThread ("first async")
do! Async.Sleep(1000)
printThread "last async"
}
member this.X() = bar
I would like to use this class and invoke X from C#. The problem is X returns an Async<'T>. However, it is bad practice to expose F# specific types. So best practice is to return a Task. However Async.StartAsTask is kind of problematic since it will cause the code run in a seperate thread. What I want is I want to return a Task but also it should behave as Async.StartImmediate. Thus the non async part of the code should run in the original main thread. Here I assume I run it from UI thread so that all calls will return the same thread ID. In other words I want a Async.StartImmediate but returning a task.
Is this achieavable ?

You can turn Async<'T> into Task<'T> using the Async.StartAsTask<'T> method.
I'd generally recommend making things easy for the C# users and extend the F# implementation with an additional method that returns Task<'T>. Following the usual naming convention, you can call the F# version AsyncFoo and the C#-friendly version FooAsync.
Looking at your example, I'd go with something like this:
type public Class1() =
let printThread (message) =
printfn "%s %A" message Thread.CurrentThread.ManagedThreadId
let bar =
printThread ("first bar")
async {
printThread ("first async")
do! Async.Sleep(1000)
printThread "last async"
}
member this.AsyncFoo() = bar
/// Expose C#-friendly asynchronous method that returns Task
member this.FooAsync() = Async.StartAsTask(bar)
/// Expose C#-friendly asynchronous method that returns Task
/// and takes cancellation token to support cancellation...
member this.FooAsync(cancellationToken) =
Async.StartAsTask(bar, ?cancellationToken=cancellationToken)

This Works exactly as I want (unlike the question this version returns an int as well which is plus):
type public Class1() =
let printThread (message) = printfn "%s %A" message Thread.CurrentThread.ManagedThreadId
let bar =
printThread ("first bar")
async {
printThread ("first async")
do! Async.Sleep(1000)
printThread "last async"
return 1232
}
member this.convertToTask<'T> (asyn : Async<'T>) =
let tcs1 = new TaskCompletionSource<'T>()
let t1 = tcs1.Task
Async.StartWithContinuations
(
asyn
, (fun (k) -> tcs1.SetResult(k)), (fun exn -> tcs1.SetException(exn)), fun exn -> ())
t1
member this.X() : Task<int> = (bar |> this.convertToTask)

How about defining X like this?
member this.X() =
let t = new Task(fun () -> bar |> Async.StartImmediate)
t.RunSynchronously()
t
As far as I can tell, it does what you want. At least, this C# code:
Console.WriteLine("X " + Thread.CurrentThread.ManagedThreadId);
var c = new Class1();
c.X().Wait();
Thread.Sleep(2000);
prints this output:
X 7
first bar 7
first async 7
last async 11
Here, as seen from C#, X has the signature Task X().

Related

let vs member in F#, need to clarify something

Let's consider the following code:
type RulesStore() =
...
static member LoadAsync : Async<RulesStore> =
async {
let! r = Startup.States.GetAsStringAsync("rules") |> Async.AwaitTask
return
if String.IsNullOrEmpty r then
new RulesStore()
else
JsonConvert.DeserializeObject<RulesStore>(r);
}
This is a static method inside an object and is used to get an instance of that object, either from a stored json, or a new clean one.
Am I right to believe that if I replace:
static member LoadAsync : Async =
with
let LoadAsync : Async =
LoadAsync would be evaluated once and subsequent loads would return the same result? if I am wrong, why is this?
This is a bit more subtle. First, you are comparing let (instance) with static member (static), which adds the obvious difference between things that happen for each instance and things that are shared by all instances.
A more useful comparison is to compare regular member and let. The subtle thing is that async computations are themselves delayed, so they only run body when you execute them.
The following is a sample to illustrate this - I added one printf before the definition of async and one inside the async block, for both let and member:
type A() =
let test =
printfn "let: before async"
async {
printfn "let: inside async"
}
member x.Test =
printfn "member: before async"
async {
printfn "member: inside async"
}
member x.RunLet() = test |> Async.RunSynchronously
member x.RunMember() = x.Test |> Async.RunSynchronously
Here is what the code does:
let a = A()
// prints "let: before async"
a.RunLet()
// prints "let: inside async"
a.RunLet()
// prints "let: inside async"
a.RunMember()
// prints "member: before async"
// and "member: inside async"
a.RunMember()
// prints "member: before async"
// and "member: inside async"
As you can see, the code "inside async" runs repeatedly each time you invoke the async computation. However, the code "before async" runs only once for let and repeatedly for member.
In reality, you almost never have code before async, so this does not make much difference in typical uses, but there is some difference - with let, the async computation is constructed just once and then reused each time.

C# async / await method to F#?

I am trying to learn F# and am in the process of converting some C# code to F#.
I have the following C# method:
public async Task<Foo> GetFooAsync(byte[] content)
{
using (var stream = new MemoryStream(content))
{
return await bar.GetFooAsync(stream);
}
}
Where bar is some private field and GetFooAsync returns a Task<Foo>.
How does this translate to F#?
Here is what I currently have:
member public this.GetFooAsync (content : byte[]) =
use stream = new MemoryStream(content)
this.bar.GetFooAsync(stream)
Which returns a Task.
In F#, asynchrony is represented by the async computation builder, which is not an exact analog of Task, but can generally be used in place of one:
member public this.GetFooAsync (content : byte[]) =
async {
use stream = new MemoryStream(content)
return! this.bar.GetFooAsync(stream) |> Async.AwaitTask
}
|> Async.StartAsTask
If you are converting async/await-intensive C# code to F#, it might get cumbersome because of the difference between F#'s async and Task and the fact that you always have to call Async.AwaitTask
To avoid that you can use FSharpx library, which has a task computation expression.
let tplAsyncMethod p = Task.Run (fun _ -> string p)
// awaiting TPL method inside async computation expression
let asyncResult = async {
let! value1 = tplAsyncMethod 1 |> Async.AwaitTask
let! value2 = tplAsyncMethod 2 |> Async.AwaitTask
return value1 + value2
}
// The same logic using task computation expression
open FSharpx.Task
let taskResult = task {
let! value1 = tplAsyncMethod 1
let! value2 = tplAsyncMethod 2
return value1 + value2
}
The result of asyncResult is Async<string> and the result of taskResult is Task<string>.

Awaiting an RX subject in F#

This is the same as How do I await a response from an RX Subject without introducing a race condition?, but in F#.
The C# solution looks like:
static async void Foo()
{
var subject = new Subject<int>();
var firstInt = subject.FirstAsync().PublishLast();
firstInt.Connect();
subject.OnNext(42);
var x = await firstInt;
Console.WriteLine("Done waiting: " + x);
}
My attempt in F# is this:
let foo () =
async {
use subject = new Subject<int>()
let firstInt = subject.FirstAsync().PublishLast()
firstInt.Connect() |> ignore
subject.OnNext(42)
let! x = firstInt
printfn "Done waiting: %d" x
return ()
}
The let x! = firstInt gives the compile error This expression was expected to have type Async<'a> but here has type IConnectableObservable<int> so apparently C# does something under the hood that F# doesn't.
Is there a C# implicit interface cast at work here, that I need to do explicitly in F#? If so, I can't figure out what it is.
After further digging, it seems that C# calls GetAwaiter() under the hood when you await something. For a Subject or an IObservable, GetAwaiter returns an AsyncSubject, which isn't immediately useful in F#, but the ToTask extension method in System.Reactive.Threading.Tasks makes it useful. Apparently, you can apply ToTask directly to a Subject (or an IObservable) without going by way of GetAwaiter, so my problem is solved by changing the let! x ... statement to:
let! x = firstInt.ToTask() |> Async.AwaitTask
edit:
There's a better way
Using FSharpx.Async is a much better way of accomplishing the same thing:
open FSharpx.Control.Observable
let foo () =
async {
use subject = new Subject<int>()
subject.OnNext(42)
let! x = Async.AwaitObservable subject
printfn "Done waiting: %d" x
return ()
}

F# async ; Run asynch expression in same thread, and yet be able to wait on async operations (e.g. do!)

Experimenting some with F# async taught me that I can StartImmediate on the current running thread. This allows me, it seems, to run an async expression which can still pass out control, whenever getting inside of it to some async operation (e.g. do!), to the code outside of the async expression. Please see the simple example below:
open System.Threading
let workThenWait() = async {
printfn "async start"
do! Async.Sleep(1000)
printfn "async end"
}
let demo() =
workThenWait() |> Async.StartImmediate
printfn "main started"
// here I want to wait to the async expression in case it has passed control
printfn "main end"
demo()
The result we get is:
async start
main started
main end
async end
On the other hand, if I execute the same async expression (in this case workThenWait) using StartAsTask (inside demo), I can potentially wait on it at the end.
MY QUESTION is:
using the previous example using StartImmediate, can I run on the same thread, but ALSO wait at the end for the async expression in case some async operation (such as do!) is called and passes control forward?
I think You need Async.RunSynchronously (http://msdn.microsoft.com/en-us/library/ee370262.aspx)
update:
Ok, now I understand better what You want, and I was able to achieve this with Async.StartWithContinuations method.
Here's the code:
open System.Threading
let f() =
printfn "main thread: %A" Thread.CurrentThread.ManagedThreadId
let c1 =
async {
printfn "c1 async thread: %A" Thread.CurrentThread.ManagedThreadId
do! Async.Sleep(1000)
return "some result"
}
let continuation s =
printfn "continuation thread: %A" Thread.CurrentThread.ManagedThreadId
printfn "now the code You want after waiting and the result %s" s
Async.StartWithContinuations(
c1,
continuation,
(fun _ -> ()),
(fun _ -> ())
)
printfn "Code that runs during async computation"
Now this is definitely not very readable as the flow of the code is not obvious. I couldn't find any better solution.
You can do this with Hopac libary:
let workThenWait() = job {
printfn "async start"
do! Hopac.Timer.Global.sleep (TimeSpan.FromMilliseconds 1000.)
printfn "async end"
}
let demo() =
let promise = workThenWait() |> Promise.start |> run
printfn "main started"
// here I want to wait to the async expression in case it has passed control
let result = run promise
printfn "main end"
demo()
Hopac is both more performant and functional than async and is little known compared to how good it is. I highly recommend it.

Async Controller Actions in F#

Using C# - ASP.NET MVC 4, I can define an async controller action like:
public async Task<ActionResult> IndexWorks()
{
var data = await DownloadAsync("http://stackoverflow.com");
return Content(data);
}
Is there a way to do something similar, using F#?
I'm aware of that I could use the AsyncManager approach. I'm also aware of that #Tomas Petricek have made a quite neat AsyncActionBuilder, but it just feels like a lot of boilerplate, compared to the C# approach.
async/await uses Tasks, so you'll need to convert back and forth between Task object and F# Async objects. To convert from Task to Async, use Async.AwaitTask. To do the opposite use Async.StartAsTask. Your example becomes:
member x.IndexWorks() =
async {
let! data = Async.AwaitTask (DownloadAsync "http://stackoverflow.com")
return x.Content(data)
} |> Async.StartAsTask
Alternatively, instead of using the async computation expression, you can use a computation expression that works for Tasks out of the box. There's one in FSharpx:
let task = FSharpx.Task.TaskBuilder()
(...)
member x.IndexWorks() = task {
let! data = DownloadAsync "http://stackoverflow.com"
return x.Content(data)
}
It actually seems like a fellow programmer, Dmitry Morozov have made such thing possible. He have made a custom AsyncWorkflowController that makes it possible to return Async<ActionResult> from an ActionResult. The code for the AsyncWorkFlowController can be found at http://fssnip.net/5q.
However, his implementation makes it very difficult to debug, due to the fact that the stack trace wont be preserved when rethrowen in the custom controller. Therefore I've made a little change to make this possible:
member actionDesc.EndExecute(asyncResult) =
match endAsync'.Value(asyncResult) with
| Choice1Of2 value -> box value
| Choice2Of2 why ->
// Preserve the stack trace, when rethrow
ExceptionDispatchInfo.Capture(why).Throw()
obj() (* Satisfy return value *) } } }
Also I've changed the following line: new ReflectedControllerDescriptor(controllerType),
to new ReflectedAsyncControllerDescriptor(controllerType) - However this change is purely optional, as it wont make any difference. I just found it more logical to use the Async one.
The full code would then be:
open System
open System.Web.Mvc
open System.Web.Mvc.Async
open System.Runtime.ExceptionServices
open Unchecked
type AsyncWorkflowController() =
inherit AsyncController()
override __.CreateActionInvoker() =
upcast { new AsyncControllerActionInvoker() with
member __.GetControllerDescriptor(controllerContext) =
let controllerType = controllerContext.Controller.GetType()
upcast { new ReflectedAsyncControllerDescriptor(controllerType) with
member ctrlDesc.FindAction(controllerContext, actionName) =
let forwarder = base.FindAction(controllerContext, actionName) :?> ReflectedActionDescriptor
if(forwarder = null || forwarder.MethodInfo.ReturnType <> typeof<Async<ActionResult>>) then
upcast forwarder
else
let endAsync' = ref (defaultof<IAsyncResult -> Choice<ActionResult, exn>>)
upcast { new AsyncActionDescriptor() with
member actionDesc.ActionName = forwarder.ActionName
member actionDesc.ControllerDescriptor = upcast ctrlDesc
member actionDesc.GetParameters() = forwarder.GetParameters()
member actionDesc.BeginExecute(controllerContext, parameters, callback, state) =
let asyncWorkflow =
forwarder.Execute(controllerContext, parameters) :?> Async<ActionResult>
|> Async.Catch
let beginAsync, endAsync, _ = Async.AsBeginEnd(fun () -> asyncWorkflow)
endAsync' := endAsync
beginAsync((), callback, state)
member actionDesc.EndExecute(asyncResult) =
match endAsync'.Value(asyncResult) with
| Choice1Of2 value -> box value
| Choice2Of2 why ->
// Preserve the stack trace, when rethrow
ExceptionDispatchInfo.Capture(why).Throw()
obj() (* Satisfy return value *) } } }
Usage:
type TestController() =
inherit AsyncWorkflowController()
member x.IndexWorks() = async {
let startThread = Thread.CurrentThread.ManagedThreadId
let! data = asyncDownload "http://stackoverflow.com"
let endThread = Thread.CurrentThread.ManagaedThreadId
return ContentResult(Content = "Start = %i | End = %i" startThread endThread) :> ActionResult }
And to confirm that it actually does everything async, and is not blocking any thread from the ASP.NET Pool, use:
member x.IndexWorks() = async {
let startThread = Thread.CurrentThread.ManagedThreadId
let! data = asyncDownload "http://stackoverflow.com"
let endThread = Thread.CurrentThread.ManagaedThreadId
return ContentResult(Content = "Start = %i | End = %i" startThread endThread) :> ActionResult }
The start and end thread will differ, hence the start thread was put back into the pool, and a new was returned when the async operation had completed.
I think there might be a bunch of people trying to do something like
type SomeController() =
inherit ApiController()
member x.Get() =
let data = Download("http://stackoverflow.com")
x.Ok(data) :> IHttpActionResult // Using built in Ok, BadRequest, etc.
Where type Get() = unit -> Task<IHttpActionResult> as expected from a C# WebApi Controller
If you try to do it as the accepted answer suggests (while trying to use the built-in Ok, BadRequest, etc. methods) you run into
can't access protected members from within a lambda
To solve this I used the ExtensionMethods directly rather than try to do contort between async {} and Task that MVC is expecting
type SomeController() =
inherit ApiController()
member x.Get() = async {
let! data = DownloadAsync("http://stackoverflow.com") |> Async.AwaitTask
return System.Web.Http.Results.OkNegotiatedContentResult(data, x) :> IHttpActionResult // Pass in 'this' pointer (x) into extension method along with data
} |> Async.StartAsTask
This with the additional upcast :> IHttpActionResult you can also return different behavior BadRequest, etc from your model and still have it run async and the type signatures should work out and compile cleanly

Resources