Lots of people think, that if they use a Parallel Actions shape, they get things done in parallel. Well, rethink that. An orchestration executes in just one thread, so no chance of getting anything to run in parallel. At runtime, the shapes in the parallel shape are simply serialized.
But what is the algorithm, then?
Well, I did some tests. First of all, I created this simple orchestration:
It’s a receive shape to fire up the orchestration and then a parallel shape with four branches and five expression shapes in each. The code in each expression shape is this:
1: System.Diagnostics.Trace.WriteLine("X. Y");
where X is a number indicating the branch and Y is a sequence number within the branch. This means that X=2 and Y=3 is the third expression shape in the second branch and X=4 and Y=1 is the first expression shape in the fourth branch.
Running this orchestration I get this result from DebugView:
So as you can see, the entire first branch is executed, then the entire second branch, and so on until the fourth branch has finished. Sounds easy enough. But lets try some other scenarios like this one:
In essence I have thrown in a receive shape in branch 2 to see if branches three and four will still have to wait until branch 2 has finished.
The result can be seen here:
So as you can see, the second branch stops after the second shape because now it awaits the receive shape. Branches three and four are then executed and after I send in a message for the receive shape, the second branch completes.
So some form of parallelism is actually achieved, but only when a shape takes too long to handle. Lets see what happens with a Delay shape instead like this:
I have switched the Receive Shape for a Delay shape, and I have set the Delay shape to wait for 100 milliseconds. The result of this is the same as with the Receive shape:
Then I tried setting the Delay shape to just 1 millisecond, but this gave the same result.
With shapes that take time in two branches, like this:
And the Delay is still set at one millisecond. I get the following result:
So as you can see, the Receive shape causes branch 2 to stop executing, and the Delay shape causes branch 3 to stop executing, allowing branch 4 to execute. Branch 3 is then executed because the Delay shape has finished and finally once the message for the Receive shape has arrived, branch 2 is executed to its end.
Another thing to note is, that the Delay shape actually doesn’t make the thread sleep. If it did, we couldn’t continue in another branch once a Delay shape is run. This makes perfectly sense, since the shapes in one branch are to be seen as a mini-process within the big process, and the delay that is needed for that mini-process shouldn’t affect the other branches. This is exemplified in this process:
The third expression shape in the first branch has been updated to this code:
1: System.Diagnostics.Trace.WriteLine("1. 3");
So as you can see, even though the first branch must wait for 2 seconds, it still executes completely before the second branch is started.
- The Parallel Actions shape does NOT mean you get any multi-threading execution environment.
- Think of the PArallel Actions shape as a way of letting multiple Business Activities happen and you don’t know in what order they will occur.
- The Delay shape does not use Thread.Sleep, but instead handles things internally.