Windows Workflow Architecture

Windows Workflow Foundation (WF) raises the abstraction level for developing interactive long-running applications. Units of work are encapsulated as activities. Activities run in an environment that provides facilities for flow control, exception handling, fault propagation, persistence of state data, loading and unloading of in-progress workflows from memory, tracking, and transaction flow.

Activity Architecture

Activities are developed as CLR types that derive from either Activity, CodeActivity, AsyncCodeActivity, or NativeActivity, or their variants that return a value, Activity<TResult>, CodeActivity<TResult>, AsyncCodeActivity<TResult>, or NativeActivity<TResult>. Developing activities that derive from Activity allows the user to assemble pre-existing activities to quickly create units of work that execute in the workflow environment. CodeActivity, on the other hand, enables execution logic to be authored in managed code using CodeActivityContext primarily for access to activity arguments. AsyncCodeActivity is similar to CodeActivity except that it can be used to implement asynchronous tasks. Developing activities that derive from NativeActivity allows users to access the runtime through the NativeActivityContext for functionality like scheduling children, creating bookmarks, invoking asynchronous work, registering transactions, and more.

Authoring activities that derive from Activity is declarative and these activities can be authored in XAML. In the following example, an activity called Prompt is created using other activities for the execution body.

<Activity x:Class='Prompt'  
  xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'  
    xmlns:z='http://schemas.microsoft.com/netfx/2008/xaml/schema'  
xmlns:my='clr-namespace:XAMLActivityDefinition;assembly=XAMLActivityDefinition'  
xmlns:s="clr-namespace:System;assembly=mscorlib"  
xmlns="http://schemas.microsoft.com/2009/workflow">  
<z:SchemaType.Members>  
  <z:SchemaType.SchemaProperty Name='Text' Type='InArgument(s:String)' />  
  <z:SchemaType.SchemaProperty Name='Response' Type='OutArgument(s:String)' />  
</z:SchemaType.Members>  
  <Sequence>  
    <my:WriteLine Text='[Text]' />  
    <my:ReadLine BookmarkName='r1' Result='[Response]' />  
  </Sequence>  
</Activity>  

Activity Context

The ActivityContext is the activity author's interface to the workflow runtime and provides access to the runtime's wealth of features. In the following example, an activity is defined that uses the execution context to create a bookmark (the mechanism that allows an activity to register a continuation point in its execution that can be resumed by a host passing data into the activity).

public sealed class ReadLine : NativeActivity<string>
{
    [RequiredArgument]
    public InArgument<string> BookmarkName { get; set; }

    protected override void Execute(NativeActivityContext context)
    {
        // Create a Bookmark and wait for it to be resumed.
        context.CreateBookmark(BookmarkName.Get(context),
            new BookmarkCallback(OnResumeBookmark));
    }

    // NativeActivity derived activities that do asynchronous operations by calling
    // one of the CreateBookmark overloads defined on System.Activities.NativeActivityContext
    // must override the CanInduceIdle property and return true.
    protected override bool CanInduceIdle
    {
        get { return true; }
    }

    public void OnResumeBookmark(NativeActivityContext context, Bookmark bookmark, object obj)
    {
        // When the Bookmark is resumed, assign its value to
        // the Result argument.
        Result.Set(context, (string)obj);
    }

Activity Life Cycle

An instance of an activity starts out in the Executing state. Unless exceptions are encountered, it remains in this state until all child activities are finished executing and any other pending work (Bookmark objects, for instance) is completed, at which point it transitions to the Closed state. The parent of an activity instance can request a child to cancel; if the child is able to be canceled it completes in the Canceled state. If an exception is thrown during execution, the runtime puts the activity into the Faulted state and propagates the exception up the parent chain of activities. The following are the three completion states of an activity:

  • Closed: The activity has completed its work and exited.

  • Canceled: The activity has gracefully abandoned its work and exited. Work is not explicitly rolled back when this state is entered.

  • Faulted: The activity has encountered an error and has exited without completing its work.

Activities remain in the Executing state when they are persisted or unloaded.