In the previous section, we looked at how to execute
operations in arrays and
for loops in
parallel; however, not every problem can decompose so nicely. Most likely
you will see a way to cleanly break up a problem, but the divisions may
not be equal. Or perhaps one part of the problem may need to be subdivided
again and again in a “divide and conquer” approach.
Fortunately, the PFX allows you divide your operations however you see fit and the library will take care of scheduling and executing those pieces in parallel.
The core structure of PFX parallelism is the
Task object. Similar to
Async<'T> type, a
Task represents a body of work to be
completed later. To see what the
object offers, let’s quickly review how to write parallel programs in
Suppose you have two independent, long-running tasks. The naive implementation simply runs them in serial:
let result1 = longTask1() let result2 = longTask2()
You can improve upon this by using the thread pool as you saw earlier; however, this makes a mess of the code and prevents you from cancelling the operation or handling exceptions properly:
let mutable completed = false let mutable result1 = null ThreadPool.QueueUserWorkItem(fun _ -> result1 <- longTask1() completed <- true ) |> ignore let result2 = longTask2() // Wait until task1 complete while not completed do Thread.Sleep(0)
Here is how you can solve this problem using the PFX:
open System.Threading.Taskslet taskBody = new Func<string>(longTask1) let ...