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;
}

See Also

Concepts

Running Workflows
Creating the WorkflowRuntime