MSDN Magazine - December 2008 - (Page 55) ibility of the WF service model to design well-factored, reusable workflow activities. One feature that makes WF particularly well suited for general-purpose programming tasks is its support for asynchronous, non-blocking work. The very nature of modern Web service- and database-centric applications lends itself to asynchronous invocation, where a request is made to the service and then local resources associated with the requesting call are freed to process other work. Later, when the dispatched work is completed, execution can pick back up where it left off. ASP.NET asynchronous pages are one example of this technique. When first executed by the WF runtime, the activity’s Execute method is invoked. Execute returns ActivityExecutionStatus.Completed if the activity has performed all of its work within Execute. It returns ActivityExecutionStatus.Executing if it reaches a point where it’s done as much work as possible, and is now waiting on Figure 3 A Generic Workflow Test Harness protected Dictionary ExecuteActivity( Type activityType, IEnumerable services, params object[] inputs ) { Dictionary outputs = null; Exception ex = null; using ( WorkflowRuntime workflowRuntime = new WorkflowRuntime() ) { AutoResetEvent waitHandle = new AutoResetEvent( false ); workflowRuntime.WorkflowCompleted += delegate( object sender, WorkflowCompletedEventArgs e ) { outputs = e.OutputParameters; waitHandle.Set(); Episodic Execution }; workflowRuntime.WorkflowTerminated += delegate( object sender, WorkflowTerminatedEventArgs e ) { ex = e.Exception; waitHandle.Set(); some external stimulus, such as a response from a Web service or database call or an e-mail sent to a specific address, to continue. Figure 2 shows the Execute method for an activity that queries an external service for a credit score, given a customer ID. Since credit scoring might take minutes or even hours to complete, the workflow invokes the service asynchronously and then goes idle waiting on a result. Before going idle, the activity registers a delegate to be invoked by the runtime when the stimulus arrives. This delegate is known as a continuation (literally, a “pointer to the rest of the program”) and allows the activity author to define any logic needed to continue activity processing. The lifetime of a single workflow may consist of several such idle-continue state transitions. The runtime receives notice of the external stimulus needed to wake an idle workflow through arrival of an item (any .NET object) on a workflow queue associated with the workflow instance. In the case of an asynchronous Web service call, the code waiting on the response obtains a reference to the queue and pushes any relevant data (presumably whatever was finally received from the Web service) onto the queue. The runtime monitors the queue and invokes the registered delegate; the delegate logic can obtain the queued item and perform any necessary processing. The power of this approach stems from what happens to the workflow during idle time. Activities that return ActivityExecutionStatus.Executing from their Execute method (and are thus considered idle) are obviously doing no work for some period of time. This might be seconds, hours, days or even months of waiting on some external stimulus. During this time, there’s no need for the workflow to remain in memory consuming machine resources that could otherwise be put to better use, so the WF runtime supports the ability to automatically unload such workflows from memory and serialize them to persistent storage using a persistence service, such as SqlWorkflowPersistenceService. When the external stimulus arrives, the WF runtime reloads the workflow and continues execution as normal. }; Unit Testing Is Still Your Friend foreach ( object svc in services ) { workflowRuntime.AddService( svc ); } Dictionary parms = new Dictionary (); for ( int i = 0; i < inputs.Length; i += 2 ) { Debug.Assert( inputs[ i ] is string ); } parms.Add( (string) inputs[ i ], inputs[ i + 1 ] ); WorkflowInstance instance = workflowRuntime.CreateWorkflow( activityType, parms ); instance.Start(); waitHandle.WaitOne(); if ( ex != null ) { Assert.True( false, ex.Message ); return null; } Else { return outputs; } } } Unit testing remains relevant to your life as a programmer targeting WF. In fact, the explicit compositional nature of WF is a natural fit for authoring a battery of comprehensive tests that exercise each piece of your solution in isolation of other pieces. I’ll give you some higher-level information here, but be sure to check out Matt Milner’s Foundations column in the November 2008 issue of MSDN Magazine (msdn.microsoft.com/magazine/dd179724) for a deeper look at unit testing workflows. A common misconception when working with WF is that you can only execute entire workflows (meaning, subclassed instances of SequentialWorkflowActivity). In fact, you can execute any activity instance as a standalone workflow, which makes it easy to use a generic activity test harness to execute and validate activities in isolation or in small subsets of a larger whole. Figure 3 shows such a test harness. The basic state-oriented test pattern of “data in/execute code/ make assertions against data” works just fine for WF with a generic test harness. The WF runtime supports auto-population of December 2008 55 msdnmagazine.com http://msdn.microsoft.com/magazine/dd179724 http://www.msdnmagazine.com
Table of Contents Feed for the Digital Edition of MSDN Magazine - December 2008 MSDN Magazine - December 2008 Contents Toolbox CLR Inside Out Advanced Basics Cutting Edge Patterns In Practice Team System Real-World WF Visual Studio OBA Tools SOA Data Access Geneva Framework Test Run Foundations Windows With C++ Going Places End Bracket MSDN Magazine - December 2008 MSDN Magazine - December 2008 - (Page Intro) MSDN Magazine - December 2008 - Contents (Page Cover1) MSDN Magazine - December 2008 - Contents (Page Cover2) MSDN Magazine - December 2008 - Contents (Page 1) MSDN Magazine - December 2008 - Contents (Page 2) MSDN Magazine - December 2008 - Contents (Page 3) MSDN Magazine - December 2008 - Contents (Page 4) MSDN Magazine - December 2008 - Contents (Page 5) MSDN Magazine - December 2008 - Contents (Page 6) MSDN Magazine - December 2008 - Contents (Page 7) MSDN Magazine - December 2008 - Contents (Page 8) MSDN Magazine - December 2008 - Contents (Page 9) MSDN Magazine - December 2008 - Contents (Page 10) MSDN Magazine - December 2008 - Toolbox (Page 11) MSDN Magazine - December 2008 - Toolbox (Page 12) MSDN Magazine - December 2008 - Toolbox (Page 13) MSDN Magazine - December 2008 - Toolbox (Page 14) MSDN Magazine - December 2008 - CLR Inside Out (Page 15) MSDN Magazine - December 2008 - CLR Inside Out (Page 16) MSDN Magazine - December 2008 - CLR Inside Out (Page 17) MSDN Magazine - December 2008 - CLR Inside Out (Page 18) MSDN Magazine - December 2008 - CLR Inside Out (Page 19) MSDN Magazine - December 2008 - CLR Inside Out (Page 20) MSDN Magazine - December 2008 - CLR Inside Out (Page 21) MSDN Magazine - December 2008 - Advanced Basics (Page 22) MSDN Magazine - December 2008 - Advanced Basics (Page 23) MSDN Magazine - December 2008 - Advanced Basics (Page 24) MSDN Magazine - December 2008 - Advanced Basics (Page 25) MSDN Magazine - December 2008 - Advanced Basics (Page 26) MSDN Magazine - December 2008 - Advanced Basics (Page 27) MSDN Magazine - December 2008 - Advanced Basics (Page 28) MSDN Magazine - December 2008 - Cutting Edge (Page 29) MSDN Magazine - December 2008 - Cutting Edge (Page 30) MSDN Magazine - December 2008 - Cutting Edge (Page 31) MSDN Magazine - December 2008 - Cutting Edge (Page 32) MSDN Magazine - December 2008 - Cutting Edge (Page 33) MSDN Magazine - December 2008 - Cutting Edge (Page 34) MSDN Magazine - December 2008 - Cutting Edge (Page 35) MSDN Magazine - December 2008 - Cutting Edge (Page 36) MSDN Magazine - December 2008 - Patterns In Practice (Page 37) MSDN Magazine - December 2008 - Patterns In Practice (Page 38) MSDN Magazine - December 2008 - Patterns In Practice (Page 39) MSDN Magazine - December 2008 - Patterns In Practice (Page 40) MSDN Magazine - December 2008 - Patterns In Practice (Page 41) MSDN Magazine - December 2008 - Patterns In Practice (Page 42) MSDN Magazine - December 2008 - Patterns In Practice (Page 43) MSDN Magazine - December 2008 - Team System (Page 44) MSDN Magazine - December 2008 - Team System (Page 45) MSDN Magazine - December 2008 - Team System (Page 46) MSDN Magazine - December 2008 - Team System (Page 47) MSDN Magazine - December 2008 - Team System (Page 48) MSDN Magazine - December 2008 - Team System (Page 49) MSDN Magazine - December 2008 - Team System (Page 50) MSDN Magazine - December 2008 - Team System (Page 51) MSDN Magazine - December 2008 - Real-World WF (Page 52) MSDN Magazine - December 2008 - Real-World WF (Page 53) MSDN Magazine - December 2008 - Real-World WF (Page 54) MSDN Magazine - December 2008 - Real-World WF (Page 55) MSDN Magazine - December 2008 - Real-World WF (Page 56) MSDN Magazine - December 2008 - Real-World WF (Page 57) MSDN Magazine - December 2008 - Real-World WF (Page 58) MSDN Magazine - December 2008 - Real-World WF (Page 59) MSDN Magazine - December 2008 - Real-World WF (Page 60) MSDN Magazine - December 2008 - Real-World WF (Page 61) MSDN Magazine - December 2008 - Visual Studio OBA Tools (Page 62) MSDN Magazine - December 2008 - Visual Studio OBA Tools (Page 63) MSDN Magazine - December 2008 - Visual Studio OBA Tools (Page 64) MSDN Magazine - December 2008 - Visual Studio OBA Tools (Page 65) MSDN Magazine - December 2008 - Visual Studio OBA Tools (Page 66) MSDN Magazine - December 2008 - Visual Studio OBA Tools (Page 67) MSDN Magazine - December 2008 - Visual Studio OBA Tools (Page 68) MSDN Magazine - December 2008 - Visual Studio OBA Tools (Page 69) MSDN Magazine - December 2008 - Visual Studio OBA Tools (Page 70) MSDN Magazine - December 2008 - Visual Studio OBA Tools (Page 71) MSDN Magazine - December 2008 - SOA Data Access (Page 72) MSDN Magazine - December 2008 - SOA Data Access (Page 73) MSDN Magazine - December 2008 - SOA Data Access (Page 74) MSDN Magazine - December 2008 - SOA Data Access (Page 75) MSDN Magazine - December 2008 - SOA Data Access (Page 76) MSDN Magazine - December 2008 - SOA Data Access (Page 77) MSDN Magazine - December 2008 - SOA Data Access (Page 78) MSDN Magazine - December 2008 - SOA Data Access (Page 79) MSDN Magazine - December 2008 - SOA Data Access (Page 80) MSDN Magazine - December 2008 - SOA Data Access (Page 81) MSDN Magazine - December 2008 - Geneva Framework (Page 82) MSDN Magazine - December 2008 - Geneva Framework (Page 83) MSDN Magazine - December 2008 - Geneva Framework (Page 84) MSDN Magazine - December 2008 - Geneva Framework (Page 85) MSDN Magazine - December 2008 - Geneva Framework (Page 86) MSDN Magazine - December 2008 - Geneva Framework (Page 87) MSDN Magazine - December 2008 - Geneva Framework (Page 88) MSDN Magazine - December 2008 - Geneva Framework (Page 89) MSDN Magazine - December 2008 - Geneva Framework (Page 90) MSDN Magazine - December 2008 - Test Run (Page 91) MSDN Magazine - December 2008 - Test Run (Page 92) MSDN Magazine - December 2008 - Test Run (Page 93) MSDN Magazine - December 2008 - Test Run (Page 94) MSDN Magazine - December 2008 - Test Run (Page 95) MSDN Magazine - December 2008 - Test Run (Page 96) MSDN Magazine - December 2008 - Test Run (Page 97) MSDN Magazine - December 2008 - Test Run (Page 98) MSDN Magazine - December 2008 - Test Run (Page 99) MSDN Magazine - December 2008 - Test Run (Page 100) MSDN Magazine - December 2008 - Foundations (Page 101) MSDN Magazine - December 2008 - Foundations (Page 102) MSDN Magazine - December 2008 - Foundations (Page 103) MSDN Magazine - December 2008 - Foundations (Page 104) MSDN Magazine - December 2008 - Foundations (Page 105) MSDN Magazine - December 2008 - Foundations (Page 106) MSDN Magazine - December 2008 - Foundations (Page 107) MSDN Magazine - December 2008 - Foundations (Page 108) MSDN Magazine - December 2008 - Windows With C++ (Page 109) MSDN Magazine - December 2008 - Windows With C++ (Page 110) MSDN Magazine - December 2008 - Windows With C++ (Page 111) MSDN Magazine - December 2008 - Windows With C++ (Page 112) MSDN Magazine - December 2008 - Going Places (Page 113) MSDN Magazine - December 2008 - Going Places (Page 114) MSDN Magazine - December 2008 - Going Places (Page 115) MSDN Magazine - December 2008 - Going Places (Page 116) MSDN Magazine - December 2008 - Going Places (Page 117) MSDN Magazine - December 2008 - Going Places (Page 118) MSDN Magazine - December 2008 - Going Places (Page 119) MSDN Magazine - December 2008 - End Bracket (Page 120) MSDN Magazine - December 2008 - End Bracket (Page Cover3) MSDN Magazine - December 2008 - End Bracket (Page Cover4)
For optimal viewing of this digital publication, please enable JavaScript and then refresh the page. If you would like to try to load the digital publication without using Flash Player detection, please click here.