ExtCore icon indicating copy to clipboard operation
ExtCore copied to clipboard

Unexpected TaskBuilder behaviour

Open polytypic opened this issue 8 years ago • 3 comments

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.

polytypic avatar May 22 '16 12:05 polytypic

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.

polytypic avatar May 22 '16 16:05 polytypic

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.

jack-pappas avatar Jan 28 '17 18:01 jack-pappas

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.

polytypic avatar Jan 28 '17 20:01 polytypic