RSS Feed
Download our iPhone app
Browse DevX
Sign up for e-mail newsletters from DevX


Get Your Code Flowing Faster with Windows WorkFlow Foundation : Page 3

Activities, decisions, and rules often feel like constraints for human beings, but for applications they are the lifeblood of making things work. Windows Workflow Foundation presents a new programming paradigm that lets these declarative principles guide your coding.

Using a Windows Application as a Workflow Host
In the previous section you saw how to create a sequential workflow console application. Using the sample application, you saw how the workflow interacts directly with the user through the console. In that sample, the console application is the workflow host as it essentially hosts the workflow and executes it.

A much more realistic approach would be to use a Windows application (or ASP.NET Web application) as a workflow host, with the workflow working in the background. In this section, you will learn how to use a Windows application as a workflow host and how it interacts with the workflow.

The application you will build in this section is a simple interest rate comparator. Suppose you have some money to deposit in the bank. Some banks offer different interest rates for different currencies, and hence you want to maximize your returns by investing your money in the currency that offers the highest returns. Here are the assumptions:

  • The principle is in Singapore Dollars (SGD).
  • The interest rate for US Dollars (USD) is 5% p.a. for amounts less than or equal to US$10,000, 7% for amounts greater than US$10,000.
  • The interest rate for Chinese Yuan (CNY) is 4% p.a. for amounts less than or equal to ¥10,000, 8% for amounts greater than ¥10,000.
  • US$1 = SGD$1.59 and ¥1 = SGD$0.20.
The above interest rates and exchange rates are hypothetical and are purely used for illustration purposes only.

Creating the Workflow Library
First, create a new Sequential Workflow Library application using Visual Studio 2005 (see Figure 13).

Figure 13. Create a new Sequential Workflow Library application.
Figure 14. The completed workflow is shown.

In the Workflow Designer, drag and drop the following activities:
  • Parallel
  • Code

The Parallel activity allows you to perform two different activities in parallel.

Set the Name property of the first Code control to USDInterests and set its ExecuteCode property to CalculateUSDInterests.

Set the Name property of the second Code control to CNYInterests and set its ExecuteCode property to CalculateCNYInterests.

The workflow should now look like Figure 14.

In the code-view of Workflow1.vb, enter the code that follows in boldface type:

Public class Workflow1
    Inherits SequentialWorkflowActivity

    Private _amount As Single
    Private _USDInterestsAmount As Single
    Private _CNYInterestsAmount As Single

    Const SGDTOUSD As Single = 1.59
    Const SGDTOCNY As Single = 0.2

    Public ReadOnly Property USDInterestsAmount() As Single
            Return _USDInterestsAmount * SGDTOUSD
        End Get
    End Property

    Public ReadOnly Property CNYInterestsAmount() As Single
            Return _CNYInterestsAmount * SGDTOCNY
        End Get
    End Property

    Public WriteOnly Property Amount() As Single
        Set(ByVal value As Single)
            Me._amount = value
        End Set
    End Property

    Public Sub New()
    End Sub

    Private Sub CalculateUSDInterests( _
       ByVal sender As System.Object, _
       ByVal e As System.EventArgs)
        Dim USDEqv As Single = _amount / SGDTOUSD
        If USDEqv <= 10000 Then
            _USDInterestsAmount = CSng(USDEqv * 0.05)
        ElseIf USDEqv > 10000 Then
            _USDInterestsAmount = CSng(USDEqv * 0.07)
        End If
    End Sub

    Private Sub CalculateCNYInterests( _
       ByVal sender As System.Object, _
       ByVal e As System.EventArgs)
        Dim CNYEqv As Single = _amount / SGDTOCNY
        If CNYEqv <= 10000 Then
            _CNYInterestsAmount = CSng(CNYEqv * 0.04)
        ElseIf CNYEqv > 10000 Then
            _CNYInterestsAmount = CSng(CNYEqv * 0.08)
        End If
    End Sub

End Class
Essentially, you are doing the following:
  • Declaring three private member variables to store the principle amount (_amount), the interest amount for USD (_USDInterestsAmount), and the interest amount for CNY (_CNYInterestsAmount).
  • Defining two constants (SGDTOUSD and SGDTOCNY) containing the exchange rate of USD and CNY. For simplicity I am hard-coding the exchange here. In real-life, you can get the rate from a Web service.
  • Defining two read-only properties—USDInterestsAmount and CNYInterestsAmount—to allow the workflow host to access the calculated interest rates.
  • Defining a write-only property (Amount) to let the workflow host set the principle amount.
  • Defining the two subroutines (CalculateUSDInterests() and CalculateCNYInterests()) for the ExecuteCode property of the two Code activites. Here, you will calculate the interests for USD and CNY deposits.
As you can see, the workflow library interacts with host primarily through properties exposed by the workflow library.

Creating the Workflow Host
With the workflow library created, let's create a Windows application to act as the host for the workflow. In Solution Explorer, right-click on the solution name and add a new Windows Application project. Name the project C:\WorkFlowWindowsApplication.

Add the references to the following DLLs (see also Figure 15):

  • System.Workflow.Activities
  • System.Workflow.ComponentModel
  • System.Workflow.Runtime

  • Figure 15. Add the references to the three WF DLLs.
    Figure 16. Populate the Form1 with Label, TextBox, and Button controls as shown.

    In the default Form1, populate it with the following controls (see also Figure 16):
    • Label controls
    • TextBox controls
    • Button control
    In the code-behind of Form1, import the following namespaces:
    Imports System.Workflow.Runtime
    Imports System.Threading
    Declare the following member variable:
    Public Class Form1
        Private WaitHandle As AutoResetEvent
    In the event handler for the Calculate button, you will create an instance of the WorkflowRuntime class. The WorkflowRuntime class exposes functionality required by a host application as well as services to configure and control the workflow runtime engine. It also receives notification of changes to both the workflow runtime engine and any of its workflow instances. Here, you will add two event handlers to monitor the completion and termination events of the workflow: WorkflowCompleted and WorkflowTerminated.

    The principle amount used for calculating interest amounts is used to create an instance of the WorkflowInstance object, together with the workflow library (WorkflowLibrary1.Workflow1) you created earlier. You need to pass in the Amount property through the use of the Dictionary object:

        Private Sub btnCalculate_Click( _
           ByVal sender As System.Object, _
           ByVal e As System.EventArgs) Handles btnCalculate.Click
            WaitHandle = New AutoResetEvent(False)
            '---Create the WorkflowRuntime---
            Using workflowRuntime As New WorkflowRuntime()
                '---monitor workflow events---
                AddHandler workflowRuntime.WorkflowCompleted, _
                         AddressOf OnWorkflowCompleted
                AddHandler workflowRuntime.WorkflowTerminated, _
                   AddressOf OnWorkflowTerminated
               '---prepare the parameters to be passed into the workflow---
                Dim parameters As Dictionary(Of String, Object) = _
                   New Dictionary(Of String, Object)()
                parameters.Add("Amount", CSng(txtAmount.Text))
                '---Create and start an instance of the workflow---
                Dim workflowInstance As WorkflowInstance
                workflowInstance = _
                   workflowRuntime.CreateWorkflow( _
                      GetType(WorkflowLibrary1.Workflow1), parameters)
                '---wait for the event to be signaled---
            End Using
        End Sub
    When the workflow has completed execution, the OnWorkflowCompleted() event will be fired. Here, you will obtain the calculated interest rates exposed by the workflow (as read-only properties) through the OutputParameters collection in the WorkflowCompletedEventArgs object. As this event runs in a separate thread, you need to take special care when updating the TextBox controls by using delegates.
        '---fired when the workflow instance is completed---
        Private Sub OnWorkflowCompleted( _
           ByVal sender As Object, _
           ByVal e As WorkflowCompletedEventArgs)
            '---update the txtCNYInterests TextBox control---
            If Me.txtCNYInterests.InvokeRequired Then
                Me.txtCNYInterests.Invoke( _
                   New EventHandler(Of WorkflowCompletedEventArgs) _
                   (AddressOf Me.OnWorkflowCompleted), _
                   New Object() {sender, e})
                Me.txtCNYInterests.Text = _
            End If
            '---update the txtUSDInterests TextBox control---
            If Me.txtUSDInterests.InvokeRequired Then
                Me.txtUSDInterests.Invoke( _
                   New EventHandler(Of WorkflowCompletedEventArgs) _
                   (AddressOf Me.OnWorkflowCompleted), _
                   New Object() {sender, e})
                Me.txtUSDInterests.Text = _
            End If
        End Sub
    Figure 17. When you test the application you should be able to see the interest rate for each currency.
    Finally, service the OnWorkflowTerminated event, which will be fired when the workflow is terminated.
        Private Sub OnWorkflowTerminated( _
           ByVal sender As Object, _
           ByVal e As WorkflowTerminatedEventArgs)
        End Sub
    That's it! Right click on WorkflowWindowsApplication in Solution Explorer and select Set as Startup Project. Then press F5 to debug the application. Enter an amount to calculate the interest for each currency and click the Calculate button. You will see the interest rate for each currency (see Figure 17).

    You should also observe that you can change the logic of the application by modifying the code in the workflow. For large-scale systems, this is a great benefit as you can now modify the workflow of the system without worrying about the front end.

    In this article, you have seen the basics of Windows Workflow Foundation and how you can create workflow-enabled applications using Visual Studio 2005. In subsequent articles, I will dive into other detailed features of Windows WF.

    Wei-Meng Lee is a Microsoft MVP and founder of Developer Learning Solutions, a technology company specializing in hands-on training on the latest Microsoft technologies. He is an established developer and trainer specializing in .NET and wireless technologies. Wei-Meng speaks regularly at international conferences and has authored and coauthored numerous books on .NET, XML, and wireless technologies. He writes extensively on topics ranging from .NET to Mac OS X. He is also the author of the .NET Compact Framework Pocket Guide, ASP.NET 2.0: A Developer's Notebook (both from O'Reilly Media, Inc.), and Programming Sudoku (Apress). Here is Wei-Meng's blog.
    Email AuthorEmail Author
    Close Icon
    Thanks for your registration, follow us on our social networks to keep up-to-date