Creating a Workflow Host ApplicationĀ 

The host application interacts with Windows Workflow Foundation through the WorkflowRuntime class, or a custom class that inherits from it. You create a WorkflowRuntime object and populate it with the services that you will use during the execution of your workflows.

Host application Responsibilities

The host application's responsibilities are as follows:

  • Create one or more processes and one or more application domains.

  • Provide isolation mechanisms as needed.

  • Marshal calls between application domains as needed.

  • Start workflow instances.

  • Create custom and local services.

Additionally, a host application might do the following:

  • Control the loading and unloading of workflows from memory.

  • Listen for specific events and communicate them to a user or administrator.

  • Set time-outs and retries for each workflow.

  • Expose performance counters.

  • Write log information for debugging and diagnostics.

  • Provide custom service implementations.

  • Create localized services to meet language requirements of the hosting application and user base.

Creating the WorkflowRuntime

The default mechanism for initializing Windows Workflow Foundation is to use the WorkflowRuntime class, as follows:

Imports System
Imports System.Threading
Imports System.Workflow.Runtime
Imports System.Workflow.Runtime.Hosting

Class Program

    Shared Sub Main()
        Using workflowRuntime As WorkflowRuntime = New WorkflowRuntime()
        End Using
    End Sub
End Class
using System;
using System.Threading;
using System.Workflow.Runtime;
using System.Workflow.Runtime.Hosting;

class Program
{
    static void Main(string[] args)
    {
        using (WorkflowRuntime workflowRuntime = new WorkflowRuntime())
        {
        }
    }
}

In the using statement body, a WorkflowRuntime object is initialized and ready for use. At this point, you can create event handlers to handle events that are raised by the runtime engine, retrieve and configure any of the base services used by the runtime engine, and finally create and start a workflow instance. For more information about Windows Workflow Foundation services, see Windows Workflow Foundation Services.

Processing WorkflowRuntime Events

The Windows Workflow runtime engine raises several events throughout its lifetime that your host application can handle. These consist of events that notify your application when the runtime engine is Started or Stopped, and also several events that correspond to the lifetime of any running workflow instances. The procedure to create event handlers for these events follows the same event-handling pattern provided in the .NET Framework. As an example, the following code creates an event handler for the Started event raised by the workflow runtime when it begins execution.

AddHandler workflowRuntime.Started, AddressOf OnWorkflowStarted
...
Shared Sub OnWorkflowStarted(ByVal sender As Object, ByVal e As WorkflowRuntimeEventArgs)
    Console.WriteLine("WorkflowRuntime started")
End Sub
workflowRuntime.Started += delegate(object sender, WorkflowRuntimeEventArgs e)
{
    Console.WriteLine("WorkflowRuntime started");
};

The following table lists the events that can be raised by the Windows Workflow runtime engine that pertain to the workflow runtime engine itself.

Event Description

ServicesExceptionNotHandled

Raised when a service that is derived from the WorkflowRuntimeService abstract class calls the RaiseServicesExceptionNotHandledEvent method, because an exception occurs during workflow execution that the service cannot handle.

Started

Raised when the workflow runtime engine starts running.

Stopped

Raised when the workflow runtime engine stops running.

The following table lists the workflow instance events that can be raised by the workflow runtime engine.

Event Description

WorkflowAborted

Raised when a workflow is stopped in the middle of processing.

WorkflowCompleted

Raised when a workflow completes processing.

WorkflowCreated

Raised when a workflow is instantiated.

WorkflowIdled

Raised when a workflow enters the idle state.

WorkflowLoaded

Raised when a workflow is recreated from a storage medium.

WorkflowPersisted

Raised when the current state of the workflow is persisted to a storage medium.

WorkflowResumed

Raised when a workflow resumes executing after it has been stopped or unloaded.

WorkflowStarted

Raised when a workflow starts running.

WorkflowSuspended

Raised when a workflow enters the suspended state.

WorkflowTerminated

Raised when a workflow is terminated.

WorkflowUnloaded

Raised when a workflow is unloaded.

WorkflowAbort Conditions

There are several different conditions that can occur during the execution of a workflow that can raise the WorkflowAborted event. For example, a host application can intervene in the process by calling the Abort method from a WorkflowInstance object. In this case, the reason is known and the logic to handle this can easily be created in the host application itself.

There are conditions however when the Windows Workflow Foundation runtime engine will abort a workflow. An example of this condition is a result of the runtime engine failing to terminate a workflow instance. A common scenario related to this condition concerns the SqlWorkflowPersistenceService. If the workflow runtime engine needs to terminate a workflow and the SqlWorkflowPersistenceService is active, the runtime engine will attempt to persist the workflow state. However, if a SqlException is thrown during the persistence operation, the runtime engine will have to abort the workflow instance. When this occurs, you can use a TrackingService to dump the exception information in order to debug the scenario that caused the runtime engine to abort the workflow instance.

Determining Workflow Terminated Source

The WorkflowTerminated event can be raised either programmatically through the host application, by using a TerminateActivity in a workflow or as a result of an uncaught exception. If your host application needs to perform certain logic based on the type of action that caused the workflow to terminate, there are several key pieces of logic you will need to check. The following table shows different states of a workflow and where to look for information regarding the reason for termination.

Action Workflow Status Activity Execution Status Terminate or Suspend Info

Normal Execution

Completed

Closed

NULL

TerminateActivity (Reason specified and not NULL)

Terminated

Executing

Reason specified in Workflow design

TerminateActivity (Reason is NULL)

Terminated

Executing

Exception of type Workflow Terminated was thrown

Terminated from host application

Terminated

Executing

Reason specified in Terminate method parameter

Unhandled Exception

Terminated

Closed

Message of the Exception causing the termination

Unhandled Exception in Fault Handler

Terminated

Closed

Message of the Exception causing the termination

The location in the workflow where an exception was thrown can be found by walking the workflow graph and checking the status of each Activity at the time of the termination. The following code demonstrates how to accomplish this if the exception is thrown from a FaultHandlerActivity.

Private Function isExceptionfromFaultHandler(ByVal rootActivity As Activity) As Boolean
    If rootActivity Is Nothing Then
        Return False
    End If
    If TypeOf rootActivity Is CompositeActivity Then
        If TypeOf rootActivity Is FaultHandlersActivity Then
            If rootActivity.ExecutionStatus = ActivityExecutionStatus.Closed Then
                Return True
            End If
        End If

        For Each act As Activity In (CType(rootActivity, CompositeActivity)).Activities
            If isExceptionfromFaultHandler(act) Then
                Return True
            End If
        Next
    End If
    Return False
End Function
bool isExceptionfromFaultHandler(Activity rootActivity)
{
    if (rootActivity == null)
        return false;
    if (rootActivity is CompositeActivity)
    {
        if (rootActivity is FaultHandlersActivity)
        {
            if (rootActivity.ExecutionStatus == ActivityExecutionStatus.Closed)
                return true;
        }

        foreach (Activity act in ((CompositeActivity)rootActivity).Activities)
            if (isExceptionfromFaultHandler(act))
                return true;
    }
    return false;
}

Running Workflows

Workflow instances can be started in two ways: Through workflow types or through XAML-based workflow markup.

To start a workflow instance through a workflow type, call the CreateWorkflow method, passing in the System.Type of the workflow, and then call Start.

Dim workflowInstance As WorkflowInstance
workflowInstance = workflowRuntime.CreateWorkflow(GetType(Workflow1))
workflowInstance.Start()
WorkflowInstance instance = workflowRuntime.CreateWorkflow
    (typeof(WorkflowApplication.Workflow1));
instance.Start();

To start a workflow instance using workflow markup only, call the CreateWorkflow method, passing in the XmlReader containing the workflow definition in either a file or stream, and then call Start.

Dim workflowInstance As WorkflowInstance
workflowInstance = workflowRuntime.CreateWorkflow(workflowDefinitionReader)
workflowInstance.Start()
WorkflowInstance instance = workflowRuntime.CreateWorkflow(workflowDefinitionReader);
instance.Start();
NoteNote

If you are using a workflow markup file with a code-separation file, you must pass the workflow type into CreateWorkflow instead of passing in the workflow markup file.

By default, workflows are started asynchronously by the Windows Workflow runtime engine. To make sure that your host application does not close before your workflow has finished executing, you must use synchronizing threading objects that are provided by the .NET Framework, such as the AutoResetEvent object. The following code example shows how to create and start the workflow runtime, start a workflow instance, and exit by using an AutoResetEvent when the WorkflowRuntime object raises the WorkflowCompleted event.

Class Program

    Shared WaitHandle As New AutoResetEvent(False)

    Shared Sub Main()
        Using workflowRuntime As New WorkflowRuntime()
            AddHandler workflowRuntime.WorkflowCompleted, AddressOf OnWorkflowCompleted

            Dim workflowInstance As WorkflowInstance
            workflowInstance = workflowRuntime.CreateWorkflow(GetType(Workflow1))
            workflowInstance.Start()
            WaitHandle.WaitOne()
        End Using
    End Sub

    Shared Sub OnWorkflowCompleted(ByVal sender As Object, ByVal e As WorkflowCompletedEventArgs)
        WaitHandle.Set()
    End Sub
End Class
static void Main(string[] args)
{
    using (WorkflowRuntime workflowRuntime = new WorkflowRuntime())
    {
        AutoResetEvent waitHandle = new AutoResetEvent(false);

        workflowRuntime.WorkflowCompleted += delegate(object sender,
            WorkflowCompletedEventArgs e)
        { 
            waitHandle.Set(); 
        };
        
        WorkflowInstance instance = workflowRuntime.CreateWorkflow
            (typeof(WorkflowApplication.Workflow1));

        instance.Start();

        waitHandle.WaitOne();
    }
}

Windows Workflow Foundation does not have any restrictions on the execution environment of the hosting application. For instance, some host application environments may require that several processes execute in several application domains, each with its own threading model independent of the other executing processes. In this way, Windows Workflow Foundation remains portable and extensible as underlying hosting architectures change.

NoteNote

Windows Workflow Foundation uses the .NET thread pool. If your host application is multi-threaded and uses the .NET thread pool extensively, you may starve the .NET thread pool. This could cause timeouts when a persistence service tries to complete a persistence transaction because Transaction objects also use the .NET thread pool.

See Also

Reference

WorkflowRuntime
Start
CreateWorkflow
Started
Stopped
ServicesExceptionNotHandled
WorkflowAborted
WorkflowCompleted
WorkflowCreated
WorkflowIdled
WorkflowLoaded
WorkflowPersisted
WorkflowResumed
WorkflowStarted
WorkflowSuspended
WorkflowTerminated
WorkflowUnloaded

Concepts

How to: Add and Remove Workflow Services
Workflow and Application Communication

Other Resources

Windows Workflow Foundation Services
Developing Workflow-Enabled Applications

Footer image

Send comments about this topic to Microsoft.