Workflow 4 parallel and compensation activities

So I’m looking into workflow foundation 4 (using Visual Studio 2010 Beta 2). Let’s look at the parallel activity included within. The parallel activity will schedule all of its child activities asynchronously and then wait until all children have completed or the CompletionCondition evaluates to True.

Let’s do a little experiment: Start Visual Studio and create a new workflow console application.

Drag a Sequence activity to the designer. In it add a WriteLine activity and a Parallel activity.

Drag a sequence activity inside the parallel activity. It will automatically split up to allow other branches:

image

Rename this sequence to left, then add a WriteLine activity, a Delay and another WriteLine activity.

Repeat this for the right branch, calling it Right. Now we only need to add two variables to time the delays. Select the Start sequence, and on the bottom of the designer click on the variables button. This will open the variables window:

image

In here define two variables leftDelay and rightDelay and make them of type TimeSpan using the dropdown combobox and select “Browse for Types…”. This should open the “Browse and Select a .NET Type” dialog. One of the new things I like about this window is that you can search for a type:

image

Finally we should end up with this:

image

Run and you should get this:

image

As you can see the parallel activity will now execute both left and right branches. But what if you want one of the branches to stop because another branch has done all that is needed? For that we can use the Parallel’s activity CompletionCondition. When one of the branches of the parallel activity completes, the parallel activity will check its CompletionCondition. If set to false, it will allow other braches to continue. Otherwise it will cancel the other, still running, branches.

So let’s test this. Click on the parallel activity and add a new boolean variable called stopProcessing (I’ve renamed the parallel activity Race, so that’s set as the stopProcessing variable’s scope):

image

Now set the parallel activity CompletionCondition to this variable by clicking the activity and using the property window:

image

Next add to each branch an assignment activity after the last writeline to set the stopProcessing to true:

image

Run: you should see one branch complete while the other never does:

image

And what about doing something when you get cancelled?

To do this we need to use a CancellationScope. A CancellationScope allows you to define what needs to be done when a branch gets cancelled, for example in a parallel activity because another branch completed with the CompletionCondition set to True.

Let’s try this. Inside the parallel activity drag a CancellationScope. Then drag the left branch in it. Repeat with a new CancellationScope for the right branch. Drag a WriteLine activity into each CancellationScope’s CancellationHandler. For example the left side should write “Left was cancelled” in the CancellationHandler:

image

Run again: You should now see one side complete, and the other being cancelled:

image

WARNING: Although you might think it is a good idea to schedule as much work as possible in parallel, this will not make your orchestration faster. WF will still schedule all activities on the same thread, so if your activities never go idle, it will take the same amount of time as if you’re using a sequence. Only if each branch in the parallel activity needs to wait on some response will using the parallel activity make a difference.