Welcome

You have reached the blog of Keith Elder. Thank you for visiting! Feel free to click the twitter icon to the right and follow me on twitter.

Part 3: Leveraging Workflow Foundation – Understanding the Runtime

Posted by Keith Elder | Posted in Workflow Foundation | Posted on 05-11-2007

Workflow Foundation‘s “brain” is the runtime.  The runtime’s main function is to handle all workflow instances, load the appropriate services, and keep track of what needs to happen next.   Before jumping in with Workflow Foundation it is important to understand the pieces that make up the workflow runtime and where the extensibility points within the runtime are located.  In this part, Understanding the Runtime, we’ll look at the pieces that makeup the runtime and discuss various things developers will want to consider.  To get started let’s look at a simple example of starting the runtime and executing a workflow. 

            using (WorkflowRuntime runtime = new WorkflowRuntime())
            {
                AutoResetEvent waitHandle = new AutoResetEvent(false);
                WorkflowInstance instance = runtime.CreateWorkflow(typeof(WorkflowConsoleApplication3.Workflow1));
                instance.Start();
                waitHandle.WaitOne();
            }

As we can see from the example above hosting the workflow runtime is really simple in this context.  Essentially once our runtime is created we use it to create our workflow from a type and then start our workflow instance.  The truth of the matter is the runtime isn’t really doing anything other than loading our workflow.  In other words in any application that leverages Workflow Foundation there would be a lot more lines of code to setup the runtime.  Workflow runtimes need to take into account several other factors before hitting the production floor such as setting up additional services and events for monitoring.   There are three things in particular developers starting out with Workflow Foundation should consider. 

One – Don’t Re-instantiate the runtime for every workflow instance

The first thing I recommend to developers starting out with Workflow Foundation is to use a singleton pattern or a factory pattern to make sure there is only one running instance of the WorkflowRuntime.  The reason we want one instance is there is a lot of overhead setting up and tearing down the WorfklowRuntime.  To give you an idea of the time it takes to just setup the runtime I ran a quick benchmark on my dual core 2.0GHz notebook.  The average time in milliseconds was between 40-42.  While that may not seem like a lot of time remember the runtime didn’t have to read any settings from the app.config file and it wasn’t using any additional services nor events.  It isn’t unusual to see one-two hundred millisecond start up times once you start getting into a production scenario depending on the amount of services.  Other than startup time the other reason we want to do this is we do not want workflow runtimes competing against each other.

Two – Understand Services

The second thing we need to familiarize ourselves with are services.  Think of workflow services as the main features of the runtime and an extensibility point whereby new features can be added.  For example tracking, scheduling, persistence, and profiling are services that ship out of the box.  By default the runtime uses the DefaultWorkflowSchedulerService.  This service handles how workflow instances are scheduled and manages the threads that runs workflows asynchronously.  While this is great the runtime uses this by default it doesn’t work in all scenarios.  Specifically if you are hosting within IIS or need to run workflows synchronously.  Other services such as the SqlWorkflowPersistenceService and the SqlTrackingService are unique services that allow developers to leverage SQL Server to store persistence and tracking information.  SQL Server schema information for these services is provided with the .Net 3.0 framework. Schemas and stored procedures for persistence and tracking can be found in the following location:

c:\windows\Microsoft.Net\Framework\v3.0\Windows Workflow Foundation\SQL

For more information about the various services and their roles be sure to browse the following links that discuss the various services in detail on MSDN.  We’ll look at several of these services down the road in another part of this series. 

Three – Events

The third thing we need to consider are the runtime events.  For example, a question often asked by developers starting out with Workflow Foundation is “How do I get properties out of my workflow after it runs?”.  In other to do this we have to use one of the events created by the runtime called WorkflowCompleted.  This event is fired once a workflow is completed and will give us access to the WorkflowCompletedEventArgs that provides access to output parameters.  For example if we had a workflow that calculated the max loan amount a client qualifies for that code may look something like this:

workflowRuntime.WorkflowCompleted += delegate(object sender, WorkflowCompletedEventArgs e) 
                { 
                    waitHandle.Set();
                    int maxLoanAmount = (int)e.OutputParameters["MaxLoanAmount"];
                    Console.WriteLine(maxLoanAmount.ToString());
                };

This may seem a little weird at first but it does make sense if you consider long running workflows that may take several minutes to run or even months.  Workflows are more complicated than calling a single method and this is why the output parameters are in the completed event because it isn’t until the workflow gets down that we have all of our calculations.   Just remember what was said earlier about the default scheduling service.  If you are running calculated workflows like the example above that calculates if a person qualifies for a loan amount using the built-in rules engine of workflow more than likely it is going to need to run synchronously and therefore the default scheduler would need to be replaced by the manual scheduler within the runtime.

Of course there are others to consider as well such as WorkflowTerminated.  Depending on how the runtime is hosted your workflow you may want to be alerted when the runtime starts or stops and when workflows are persisted.  For example if you are hosting workflows within a Windows Service that is expected to stay running wire up events that sent alerts when the workflow terminated or suspended workflows unexpectedly.

Other Considerations

Hosting the workflow runtime isn’t tricky and can be configured via application config (app.config or web.config) files or within code.  For web hosted applications and services the web.config file is the best place to store workflow runtime information since this allows the runtime to be altered without having to be redeployed.  For windows services and possibly Winforms you may chose to go the API route. 

Developers looking to leverage Workflow Foundation in larger scenarios are going to ultimately want to customize the runtime.  This could be changing how workflows are persisted and tracked to creating their own custom scheduler.  The nice thing is Workflow Foundation is ready to be customized. 

One idea of extensibility may be using the file system to store workflows instead of SQL Server.  For those looking for this option you can find an example already done on MSDN here.  Another extensibility point is scheduling.  There was an example we ran into at work whereby workflow runtimes using the manual scheduler in IIS could not call other workflows.  A custom scheduler did the trick.  You can read more about that problem and resolution here.

In part four of Leveraging Workflow Foundation we’ll look at hosting workflows and how this knowledge in applied in various scenarios.

Part 1: Leveraging Workflow Foundation – It is just an API
Part 2:  Leveraging Workflow Foundation – Invest in your Workflow Infrastructure

 

Technorati tags: ,

Comments (1)

Great article, Keith!

Write a comment