WF Activities—Running the Workflow


Jump to: navigation, search
CSharp-Online.NET:Articles
.NET Articles

WF Activities

© 2007 Bruce Bukovics

Running the Workflow

Now that the workflow is fully implemented, you can turn your attention to the code that executes it. Since this is a Console application, the project template generates boilerplate code for the Program.cs file to host the workflow runtime and execute the workflow.

However, to test this application, you’ll want to execute the workflow multiple times with different input parameters each time. To facilitate this, the standard Program.cs that comes with the project template requires a few adjustments. The revised code is shown in Listing 3-3.

Listing 3-3. Complete Program.cs File

#region Using directives
 
using System;
using System.Collections.Generic;
using System.Threading;
using System.Workflow.Runtime;
 
#endregion
 
namespace OrderEntryCode
{
    /// <summary>
    /// Execute OrderEntry workflow with CodeActivity
    /// </summary>
    public class Program : IDisposable
    {
        private WorkflowRuntime _workflowRuntime;
        private AutoResetEvent _waitHandle = new AutoResetEvent(false);
 
        public Program()
        {
            InitializeWorkflowRuntime();
        }
 
        #region IDisposable Members
 
        /// <summary>
        /// Dispose of the workflow runtime
        /// </summary>
        public void Dispose()
        {
            _workflowRuntime.StopRuntime();
            _workflowRuntime.Dispose();
        }

The Program class implements IDisposable. This isn’t strictly a requirement, but is done in order to allow use of the using syntax in the Main method. Within the Dispose method, StopRuntime and Dispose are called on the WorkflowRuntime instance. This ensures that all resources used by the workflow runtime engine are released and available for garbage collection.

#endregion
 
        /// <summary>
        /// Start the workflow runtime
        /// </summary>
        private void InitializeWorkflowRuntime()
        {
            _workflowRuntime = new WorkflowRuntime();
            _workflowRuntime.WorkflowCompleted
                += delegate(object sender, WorkflowCompletedEventArgs e)
                {
                    _waitHandle.Set();
                };
            _workflowRuntime.WorkflowTerminated
                += delegate(object sender, WorkflowTerminatedEventArgs e)
                {
                    Console.WriteLine(e.Exception.Message);
                    _waitHandle.Set();
                };
        }

During construction of the Program class, an instance of the WorkflowRuntime class is initialized. This class represents the workflow runtime engine. During initialization, the code also adds event handlers for the WorkflowCompleted and WorkflowTerminated events. These events are handled in order to know when each instance of the workflow has completed.

/// <summary>
        /// Run the workflow
        /// </summary>
        /// <param name="wfArguments"></param>
        public void RunWorkflow(Dictionary<String, Object> wfArguments)
        {
            //create the workflow instance and start it
            WorkflowInstance instance = _workflowRuntime.CreateWorkflow(
                    typeof(OrderEntryCode.Workflow1), wfArguments);
            instance.Start();
 
            //wait for the workflow to complete
            _waitHandle.WaitOne();
        }

A RunWorkflow method is added to make it easier to execute an instance of the workflow. It calls the CreateWorkflow method of the WorkflowRuntime instance to create a workflow. This method returns a WorkflowInstance which is then started using the Start method. The RunWorkflow method then waits for the AutoResetEvent instance (_waitHandle) to be signaled. This is necessary since workflow execution is asynchronous within the runtime engine. The _waitHandle variable is signaled by the WorkflowCompleted and WorkflowTerminated event handlers.

static void Main(string[] args)
        {
            using (Program instance = new Program())
            {
                //create a dictionary with input arguments
                Dictionary<String, Object> wfArguments
                    = new Dictionary<string, object>();
                wfArguments.Add("AccountId", 1001);
                wfArguments.Add("SalesItemId", 501);
                //run the workflow
                instance.RunWorkflow(wfArguments);
 
                //change the parameters and run the workflow
                //one more time with another account and item
                wfArguments.Clear();
                wfArguments.Add("AccountId", 2002);
                wfArguments.Add("SalesItemId", 502);
                instance.RunWorkflow(wfArguments);
 
                //try the workflow gain, this time the account
                //should have insufficient funds for the order.
                wfArguments.Clear();
                wfArguments.Add("AccountId", 1001);
                wfArguments.Add("SalesItemId", 502);
                instance.RunWorkflow(wfArguments);
 
 
                //run the workflow again with an invalid account
                wfArguments.Clear();
                wfArguments.Add("AccountId", 9999);
                wfArguments.Add("SalesItemId", 501);
                instance.RunWorkflow(wfArguments);
 
                Console.WriteLine("Press any key to exit");
                Console.ReadLine();
            }
        }
    }
}

The static Main method is where everything comes together. Workflow parameters are added to a Dictionary of Object that is keyed by a String. The parameter names exactly match the dependency properties added to the workflow (AccountId and SalesItemId). The workflow is then executed by calling the RunWorkflow method which accepts the Dictionary of parameters.

The workflow is executed a total of four times, each time a different combination of AccountId and SalesItemId are passed. These combinations were chosen to demonstrate the results of each possible execution path within the workflow. When you execute this program, the results look like this:

Order entered for account 1001, Item id 501 for 59.95
Order entered for account 2002, Item id 502 for 199.99
Item 502 invalid or AccountId 1001 credit of 100.00 insufficient
AccountId 9999 is invalid
Press any key to exit


Previous_Page_.gif Next_Page_.gif


Personal tools