a trace of thought on...BizTalk Server, Team Foundation Server, Windows Mobile, etc. RSS 2.0
 Friday, December 31, 2004

BizTalk 2004 has some very useful behavior around parallel execution and scope-level timeouts that it is helpful to have a good understanding of.

What follows is a series of experiments & associated findings that should shed some light on this area.

Experiment One: 

One restriction when using the parallel shape is that if multiple branches make use of a given orchestration variable, you can get a compiler error:

error X2226: 'someVar': if shared data is updated in a parallel then all references in every task must be in a synchronized or atomic scope

In the experiment below, we are accesing ‘someVar’ in both parallel branches - each within an expression shape that also calls Thread.Sleep (the left hand for 10 seconds, the right hand for 30.)  To address the compiler error just noted, we have a scope around each usage with the ‘Synchronized’ flag on the scopes set to ‘true’.

The trace messages shown to the right of the diagram tell us that, indeed, the execution of Scope 2 and Scope 3 is completely serialized (in this case, Scope 2 completes before Scope 3 begins.)

This experiment also tells us something unrelated (but useful): that an exception will not interrupt “user code”.  By “user code” we refer to code in an expression shape, i.e. not using an orchestration “intrinsic” such as a standard Delay shape or a Receive shape, etc.  Notice via the timings that the exception thrown in the left-hand branch doesn’t abort the Thread.Sleep in the right-hand branch.  The exception is caught only after the Thread.Sleep in the right-hand branch completes (though the final trace message in the right hand branch – ‘after 30 sec’ – does not execute.)  This is important to understand if you have expression shapes in orchestrations which are making blocking calls to .NET components, DCOM servers, etc.


Experiment Two:

If we eliminate the ‘someVar’ reference in the expression shapes above, we find that the scopes do not execute serially – whether the scope synchronization flag is set to true OR false.  Notice below (via the timings) that the sleep operations are executed at the same time - so it is the presence of the common variable in the expression that forces the synchronization!

We now have a 20 second gap after sleeping for 10 seconds (because the exception we throw still doesn’t interrupt us).

Experiment Three:

We would like to use a given instance of a .NET object without imposing the use of synchronized scopes.  As it happens, if we have a .NET object that is pointed at by two references (i.e. someVar and someVar2 - where someVar2 was set equal to someVar with a simple assignment), the requirement that the orchestration compiler normally imposes regarding the use of a synchronized scope goes away.

In the orchestration below, the left branch is using someVar, and the right branch uses someVar2.  The trace indicates that the sleep operations happen at same time (though once again the exception doesn’t interrupt the right-hand side and is caught only when the right-hand completes.)

Lesson: If you have a .NET component (that you know to be thread-safe) you wish to use in an orchestration - and you wish to use a single instance of it - you will need to have multiple references to that same instance to use in each branch of a parallel shape.  (The synchronized-scope alternative is likely unacceptable!)  The first variable declaration of your component might use the default constructor, while the others will have “Use Default Constructor” set to false and will be assigned to the first.

Experiment Four:

Now, there is more to be said regarding exceptions and what they will interrupt in parallel branches.  If instead of using a Thread.Sleep we use a Delay shape (or a Receive shape, etc.) we find that throwing an exception in one branch of the parallel shape will indeed interrupt the other branch(es).  Notice in the timings below that the Delay 30sec shape does not complete once the exception in the left-hand branch in thrown.  Particularly when you are structuring real-world business flows, this is an important and quite useful behavior.


Experiment Five:

The behavior of exceptions in parallel flows is closely related to another behavior in BizTalk 2004 - that of what BizTalk is prepared to "interrupt" when a long-running scope has exceeded the timeout value that has been configured for the scope.  A Delay shape (or Receive, etc.) will indeed be interrupted when the timeout expires (and a TimeoutException will be thrown).  (Note that for an atomic scope, the timeout governs the maximum time to allow prior to aborting the transaction.)  See the timings below and note that the Delay 30sec shape does not complete.

On the other hand, as you might expect at this point, a blocking call in an expression shape (like a Thread.Sleep or a DCOM call, etc.) will not be interrupted.  However, the exception will be raised when the blocking call eventually returns:

Summary:

  • The Synchronized flag on a scope will only cause synchronized (serialized) behavior among “peers in parallel branches” when shared variable or message state is involved.  (This is ignoring any transactional semantics you might layer on top – which is beyond the scope of this article!)
  • If you have a thread-safe .NET component that you wish to use in an orchestration from multiple parallel branches, strongly consider having multiple variables point to a common instance.  The first instance might have “Use Default Constructor = true”, while the remaining variables will have that flag set equal to false and be assigned to the first instance in an expression shape: someVar2 = someVar1;
    someVar3 = someVar1;
    someVar4 = someVar1, etc.

    An alternative is to use scope-local variables that are assigned to a global instance.
  • A line of code in an Expression shape will not be interrupted by either an exception in a parallel branch or a TimeOutException arising from a timed-out scope.
  • A Delay shape or Receive shape, etc. will be interrupted by either an exception in a parallel branch or a TimeOutException arising from a timed-out scope.
Friday, December 31, 2004 12:21:40 PM (Central Standard Time, UTC-06:00)  #    Comments [4] -
BizTalk Insights
Archive
<February 2010>
SunMonTueWedThuFriSat
31123456
78910111213
14151617181920
21222324252627
28123456
78910111213
About the author:

Scott Colestock lives, writes, and works as an independent consultant in the Twin Cities (Minneapolis, Minnesota) area.

© Copyright 2010
Scott Colestock
Sign In
All Content © 2010, Scott Colestock
DasBlog theme 'Business' created by Christoph De Baene (delarou)