While implementing Windows Workflow (WF) applications, there are situation when the workflow has to be scheduled manually. By default one workflow is scheduled by using DefaultWorkflowSchedulerService. Additionally to default scheduler, Windows Workflow provides the ManualWorkflowSchedulerService.
The Manual Scheduler service is implemented to schedule the workflow in one thread only. This is very useful when you want strictly to control the number of threads in your application.
If you are asking yourself now, what specific scenario this could be, just think about workflow hosting in IIS environment. Because IIS has limited number of threads which can be allocated, running of the workflow within default scheduler could result in an implicit deadlock. Be sure what scheduler is used if the workflow is hosted in IIS or some similar host. One good example which describes differences between schedulers can be found in Scott's Ode2Code blog.
Following code shows how to start the workflow by using of Manual-Scheduler:
WorkflowRuntime runtime = new WorkflowRuntime();
ManualWorkflowSchedulerService manualScheduler = new ManualWorkflowSchedulerService();
runtime.AddService(manualScheduler);
WorkflowInstance instance = runtime.CreateWorkflow(typeof(SomeWorkflow));
instance.Start(); manualScheduler.RunWorkflow(instance.InstanceId); |
This code shows how to do the same thing with the Default-Scheduler:
WorkflowRuntime runtime = new WorkflowRuntime();
WorkflowInstance instance = runtime.CreateWorkflow(typeof(SomeWorkflow));
instance.Start(); |
So, if you use Manual Scheduler it is likely that the workflow will be executed on the same thread, which is none thread-pool thread. The Manual Scheduler is designed to do that, but there are some situations when this scheduler executes the workflow on more than one thread too. To explain this, imagine you have a workflow with external event handling. This could be for example, one delay-activity. In such cases, when the delay time is expired the activity right after delay-activity will be invoked on the different thread, which is thread-pooled. In general it is to expect, that external event handling most likely always implements some kind of listening on different thread.
If you decided to use Manual Scheduler, because you want to limit number of threads, be aware of this behavior.
There is at least one more important thing about Delay-Activity you should know. When this activity is used with Manual Scheduler you may notice that the delay-activity does not work. It means, the expected time limit seems to never be expired. To solve this problem, the Manual-Scheduler Service has additional constructor, which can be used to activate so called Active Timers:
ManualWorkflowSchedulerService scheduler = new ManualWorkflowSchedulerService(true);
|
I agree that this parameter is not well documented. But, don't be confused with the name of this parameter. As I sow it first time, I was like "Now I have to dig in the theory of relativity". The good news is that scheduler internally does nothing than registers a well known timer callback handler as shown below:
When using manual scheduling, note that the method RunWorkflow() returns after the workflow is persisted or enters a Delay-Activity. In this case you have to implement the synchronization by yourself as shown in the following example:
// How to signal that the WF is completed. m_Runtime.WorkflowCompleted += delegate(object sender, WorkflowCompletedEventArgs e) { waitHandle.Set(); };
instance = m_Runtime.CreateWorkflow(. . .);
instance.Start();
// WF is completed. bool r = m_Scheduler.RunWorkflow(instance.InstanceId);
// Here we wait on WF to be completed waitHandle.WaitOne(); |
Visit: www.daenet.eu, www.daenet.de, www.daenet.nl, www.daenet.ba.
Posted
Dec 10 2007, 11:31 PM
by
Damir Dobric