US / UK-EMEA / Contact Ask DevelopMentor a Question800.699.1932

Doing synchronous workflow execution using WorkflowApplication

by: Maurice De Beijer

The WorkflowApplication is a great way to execute your workflows in process. Usually the fact that the WorkflowApplication is asynchronous is a great thing but there are cases when a little more synchronous execution is nice. For example executing a workflow and updating the state of the user interface is much simpler when the WorkflowApplication.Run() doesn’t finish until all work is done.


The key to creating a synchronous WorkflowApplication is using its SynchronizationContext. Normally you set this to SynchronizationContext.Current so everything executes on the current UI thread. However this is still an asynchronous call and the Run doesn’t block.


Take this very simple workflow and its execution output.
 

var workflow = new Sequence()
{
    Activities = {
        new WriteLine(){ Text="Workflow is running"}
    }
};
 
var app = new WorkflowApplication(workflow);
 
Console.WriteLine("Before WorkflowApplication.Run()");
app.Run();
Console.WriteLine("After WorkflowApplication.Run()");

image


As you can see the Run() didn’t block and the message after the Run() was printed before the message from the workflow.

 

Executing the workflow synchronously

Making this workflow execute in a synchronous fashion is easy and requires only a very small change by setting the SynchronizationContext to a custom implementation.
 

var workflow = new Sequence()
{
    Activities = {
        new WriteLine(){ Text="Workflow is running"}
    }
};
 
var app = new WorkflowApplication(workflow);
app.SynchronizationContext = new SynchronousSynchronizationContext();
 
Console.WriteLine("Before WorkflowApplication.Run()");
app.Run();
Console.WriteLine("After WorkflowApplication.Run()");

image
 


The SynchronousSynchronizationContext used is real simple. The workflow internals always call the Post() method to execute work, so all we need to do is just execute the delegate passed with the state passed.
 

 

class SynchronousSynchronizationContext : SynchronizationContext
{
    public override void Post(SendOrPostCallback d, object state)
    {
        d(state);
    }
}


Executing an asynchronous workflow

Using this same SynchronousSynchronizationContext  with an asynchronous workflow works just fine. If I add the following simple bookmarked activity to the workflow and execute it I get the following result:
 

image


The code to execute the workflow is as follows
 

var workflow = new Sequence()
{
    Activities = {
        new WriteLine(){ Text="Workflow has started"},
        new MyBookmarkedActivity(),
        new WriteLine(){ Text="Workflow is done"}
    }
};
 
var app = new WorkflowApplication(workflow);
app.SynchronizationContext = new SynchronousSynchronizationContext();
app.Idle = e => Console.WriteLine("WorkflowApplication.Idle called");
 
Console.WriteLine("Before WorkflowApplication.Run()");
app.Run();
Console.WriteLine("After WorkflowApplication.Run()");
Console.WriteLine();
Console.WriteLine("Before WorkflowApplication.ResumeBookmark()");
Console.WriteLine("ResumeBookmark: {0}", app.ResumeBookmark("MyBookmark", null));
Console.WriteLine("After WorkflowApplication.ResumeBookmark()");

 

And the bookmarked activity is as follows:
 

 

class MyBookmarkedActivity : NativeActivity
{
    protected override bool CanInduceIdle
    {
        get { return true; }
    }
 
    protected override void Execute(NativeActivityContext context)
    {
        Console.WriteLine("Creating bookmark");
        context.CreateBookmark("MyBookmark", BookmarkResumed);
    }
 
    private void BookmarkResumed(NativeActivityContext context, Bookmark bookmark, object value)
    {
        Console.WriteLine("Bookmark resumed");
    }
}

Conclusion

A simple yet effective addition to the workflow runtime for that special case where the asynchronous behavior is not quite what you want but the WorkflowInvoker is not flexible enough.

Connect
Signup for our Free Newsletter!
Latest news
Twitter Feed MORE
Got an email from a developer in Holland about my Onion Architecture blog post http://t.co/Z5DTvJob Nice to have a worldwide audience! #dm
1 day ago (details)
There is something to this statement: Why Quit? Because They Have Bigger Monitors http://t.co/9FrGETG5 #dm (via @mkennedy)
1 day ago (details)
Testimonials
  • Awesome! Rod da Silva really knows his stuff and makes it interesting and gets you thinking about how you could use the product on the first day. He presents the data in a matter that makes perfect sense. Angela H.