Windows Workflow Foundation: Parallel Activities Aren't Exactly Parallel

It came as a bit of a surprise to me that Parallel activities in Windows Workflow Foundation are not in fact asynchronous.  Since investigating I've seen that several people have mentioned this fact but I thought a more descriptive example might be in order.

Consider the following sequential workflow hosted in a console application.  In it I have one parallel activity with three branches.  Each branch has two code activities.  There is a final code activity at the end of the workflow.



In each code activity I merely echo a number matching the Code activity number.  So activity Code1 displays "1" and Code2 displays "2".  Note that I have numbered them across the branches.  Code 7 displays the word "Done".  Now, if parallel activities executed their branches asynchronously you'd expect that I would see the results in a seemingly random set of "1/4", "2/5", and "3/6".  Instead what you get is this:



The Scheduler inside the WF (Formerly known as WWF) executes the first activity of each branch before moving to the second as well as moving through the branches in order.  Execution takes place on the same thread from the CLR Threadpool for each activity.

Tomorrow Soon, I'll show one example of how to make each of the branches execute asynchronously.   

Here's a link to the sample workflow project.

4 Comments

  • I don't know if I'd take this as conclusive evidence that they're not operating in parallel. How many runs did you do? It could have just been the case that they actually did run in parallel in three different threads, but the timing of the threads was such that you ended up with that order.



    It's certainly a likely possibility considering that thread 1 would have been started first, thread 2 would have been started after thread 1, and thread 3 would have been started last. Considering the pretty constant time of the simple operation in your code, there seems to be no reason to believe that it's not parallel operation. It seems likely that your test case was not sufficient to arrive at that conclusion.



    May I suggest that you make "code 1" a longer running task? If, in that scenario, you still end up with 1,2,3,4,5,6, then it would be a more conclusive assertion that the parallel task is not really parallel.

  • Charles,



    The purpose of this example wasn't to determine IF the parallel activity is asynchronous but to simply demonstrate that it IS NOT asynchronous. What I did however forget to do was to include the code so you can see for yourself. I have added a link to the source code. You can debug the individual code activities and see for yourself that they are all running on the same thread quite synchronously.

  • Don't take this as a personal attack, but this is just a very, very poorly designed test case for your hypothesis. I understand your point and what you're trying to prove, but the evidence that you presented does not demonstrate that it IS NOT asynchronous. It demonstrated that, for a given run, with each task taking a consistent time (all the tasks are trivial and let's assume the threads are scheduled to start from left to right), it's pretty obvious that 1,2,3,4,5,6 is likely the result every time.



    If you want to rely on sample runs and images to demonstrate your point, then you can PROVE, conclusively, that it's NOT asynchronous by overloading task 1 and forcing it run longer than the other tasks. If task 1 takes say 15 seconds to finish before printing a mesage and it's asynchronous, then we should see 2,3,5,6,1,4.



    If not, then we will see the same 1,2,3,4,5,6, even though task 1 takes far longer than the others to finish since there is only one thread of execution. Do you see my point? Given the evidence that you present in your post, you cannot conclude that it's not asynchronous as your test case is obviously a poor one (all tasks essentially identical in terms of time and processing requirements).



    I don't care for the code since it proves nothing; using the test procedure that you used could produce the same results, even if you run it 10000 times since each of the code tasks are identical and far too trivial. The code that you use has no explicit handling of threads, so it's pointless. Even screenshots of the threadcount of the process that hosts the workflow is useless since it's likely using some thread pool. Like I said, you can easily set up a correct task by forcing the first code task to loop 100000 times or call sleep on the thread (if possible from that context).

  • Charles,



    I understand what you're saying, I do in fact know how multithreading works. Honest! I've given talks on the subject. But this isn't a test case. I have no hypothesis, the fact that parallel activities don't run each branch asynchronously is just that, a fact. I have no need to prove it, I'm merely setting up for the next post which will be on how to run sequences asynchronously.

Comments have been disabled for this content.