In the last post we have discussed at length about different mechanisms of parameter passing and obtaining results from a workflow.In this post we will discuss about another extremely important aspect of workflow and host communication i.e. Bookmarks. Bookmarks as the name suggests is a like Bookmark for a book. When created at a particular point in the execution of the workflow , the execution is suspended and the workflow waits to be resumed.When a bookmark is resumed it starts executing exactly from the same point.
To create a Bookmark we need to define a custom native activity deriving from System.Activities.NativeActivity class. The Execute method of this custom activity accepts a System.Activities.NativeActivityContext object as parameter.NativeActivityContext provides a method called CreateBookmark which is used to create the bookmark. One of the commonly used overloads of this method is:
public Bookmark CreateBookmark(string name, BookmarkCallback callback);
BookmarkCallback is a delegate to provide a callback method.This is invoked when the Bookmark is resumed. The signature of this delegate is:
public delegate void BookmarkCallback(NativeActivityContext context, Bookmark bookmark, object value);
The last parameter “value” contains the value of any input that is passed by the host to the workflow while resuming the bookmark.
The below shows a custom activity which creates a bookmark,in the bookmark callback expects an array of integer which is set to 2 output arguments of the activity.
public class GetInput:NativeActivity
{
public OutArgument<Int32> Number1 { get; set; }
public OutArgument<Int32> Number2 { get; set; }
protected override void Execute(NativeActivityContext context)
{
context.CreateBookmark("WaitForInput",(c, b, o) =>
{
var nums = o as Int32[];
if (o != null)
{
Number1.Set(c, nums[0]);
Number2.Set(c, nums[1]);
}
});
}
protected override bool CanInduceIdle
{
get
{
return true;
}
}
}
The property CanInduceIdle indicates whether this activity puts the workflow in Idle state or not. This activity creates a bookmark and when a bookmark is created workflow goes into idle state so this is set to true.
We will use this activity in a simple sequential workflow which accepts to numbers from the command prompt, adds them and returns the result as output.
There are two workflow variables defined i and j.
These two are assigned to the out arguments of the “GetInput” activity.
Using the built-in Assign activity the sum of i and j is set to the out argument of the workflow i.e. “Result”.
We have to now execute the workflow.Here, we have to use WorkflowApplication as WorkflowInvoker does not support bookmarks.
class Program
{
static void Main(string[] args)
{
var flag = new AutoResetEvent(false);
var app = new WorkflowApplication(new MyCalculatorWorkflow());
app.Idle = (e)=>{
Console.WriteLine("Workflow is Idle..");
flag.Set();
};
app.Completed = (e) =>
{
Console.WriteLine("Workflow Completed..");
if (e.Outputs["Result"] != null) Console.WriteLine("Result is {0}",
e.Outputs["Result"].ToString());
flag.Set();
};
app.Run();
flag.WaitOne();
Console.WriteLine("Please enter number 1");
var input = Console.ReadLine();
var i = Convert.ToInt32(input);
Console.WriteLine("Please enter number 2");
input = Console.ReadLine();
var j = Convert.ToInt32(input);
flag.Reset();
app.ResumeBookmark("WaitForInput", new Int32[] { i, j });
flag.WaitOne();
Console.ReadLine();
}
The above program does the following:
- Instantiates a WorkflowApplication
- The Completed and Idle event handlers are provided to track when the workflow is going idle and to get the back the output from the workflow respectively.
- The workflow is started in asynchronous mode (as the Run method is async by default) and the main execution thread waits on the AutoResetEvent object.
- The “GetInput” activity is executed.
- A bookmark is created and workflow moves into Idle state
- The Idle event handler is executed which signals the AutoResetEvent object.
- The main thread of execution proceeds again.
- Captures two number input from the console.
- Invokes the ResumeBookmark method and passes the integer values
- BookmarkCallback is executed and it assigns the integers passed from console to the two out arguments of the “GetInputs” activity.
- The workflow is completed and completed event handler executes and prints the output of the workflow to the console.
The output of the program is shown below:


Great Article 🙂
We can also submit our .net related links on http://www.dotnettechy.com to improve traffic.
The dotnettechy.com is a community of .Net developers joined together to learn, to teach, to find solutions, to find interview questions and answers, to find .net website / blog collection and to have fun programming.
great 🙂 thanks