Reputation: 289
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.
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?
Upvotes: 3
Views: 529
Reputation: 989
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.
Upvotes: 1
Reputation: 1797
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.
Upvotes: 2