ExtCore
ExtCore copied to clipboard
Unexpected TaskBuilder behaviour
Here is a simple program using TaskBuilder
:
open System.Threading
open System.Threading.Tasks
open ExtCore.Control.Tasks
[<EntryPoint>]
let main _ =
let completed = ref false
let t = tasks {
printfn "Started"
let n = ref 10
let s = ref 0
printfn "Next while"
while 0 < !n do
printfn "Iteration"
s := !n + !s
n := !n - 1
printfn "Sum %A" !s
lock completed <| fun () ->
completed := true
Monitor.PulseAll completed
}
t.Start ()
lock completed <| fun () ->
while not !completed do
Monitor.Wait completed |> ignore
0
Running this program (Mono, but I don't expect different behavior under .Net) I get the following output:
Started
Next while
After which nothing happens. I would expect the computation to run to completion. Like when happens if you replace tasks
with async
and t.Start ()
with Async.Start t
.
BTW, this
member this.While (guard, body : Task<_>)
: Task<unit> =
if guard () then
this.Bind (body, (fun () -> this.While (guard, body)))
else
this.Zero ()
cannot possibly work. That is because tasks are fundamentally one-shot. You can create a lazy task using the task constructor as is done by delay
member __.Delay (taskThunk : unit -> Task<'T>)
: Task<'T> =
new Task<'T>(fun () ->
// Execute the task thunk to create the task.
let task = taskThunk ()
// Run the delayed task synchronously.
task.RunSynchronously ()
task.Wait ()
// Return the result of the task.
task.Result)
but, AFAICT, the resulting task can only be started once and it has to be started explicitly.
Hi Vesa, thank you for reporting this.
I've been conservative about adding new features to ExtCore to ensure everything I do add serves some real-world need and can be well-tested and optimized. I added TaskBuilder
as an experiment with the intention of finishing and testing it for correctness before release, but accidentally released it before I could get around to that.
I'll mark the type with [<Experimental>]
now to indicate it shouldn't be used until I have a chance to fix the code and get it working correctly.
BTW, I wrote a version of a Task builder
https://github.com/Hopac/Hopac/blob/master/Tests/AdHocTests/RunTask.fsi https://github.com/Hopac/Hopac/blob/master/Tests/AdHocTests/RunTask.fs
back around the time I reported the issue here. It is not thoroughly tested nor am I using it anywhere.