I am doing parallel programming using F#. With fixed number of elements, for example with 2 elements a1, a2 and a function f, I can do as follows:
let t1 = Task.Factory.StartNew(fun () -> f a1)
let t2 = Task.Factory.StartNew(fun () -> f a2)
Task.WaitAll(t1, t2)
t1.Result, t2.Result
I wonder how I could do the same with a list of elements:
let ts = List.map (fun a -> Task.Factory.StartNew(fun () -> f a))
Task.WaitAll(ts)
List.map (fun (t: Task<_>) -> t.Result) ts
Visual Studio spots that Task.WaitAll couldn't accept Task< T > list as its parameter. Task.WaitAll can have Task [] as its argument but it makes no sense because I need to get Result for next computation.
As Robert explains, if you want to call WaitAll
, you'll have to cast the elements sequence to the base type Task
and then convert it to an array. You can define your extension member for Task
to make the tas simpler:
type System.Threading.Tasks.Task with
static member WaitAll(ts) =
Task.WaitAll [| for t in ts -> t :> Task |]
I'm using array comprehension and cast instead of Seq.cast
because Seq.cast
takes untyped IEnumerable
- so F# infers better type for the extension method.
Another option is not to call WaitAll
at all - if you don't do it, the Result
properties will block until a task completes. This means that you'll block the thread anyway (there may be a bit larger number of blockings, but I'm not sure if it affects performance too much). If you use List.map
to collect all results, the behavior would be almost the same.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With