ASP.NET and DefaultWorkflowSchedulerService

QUESTION: Can I use DefaultWorkflowSchedulerService instead of ManualWorkflowSchedulerService in my IIS hosted WorkflowRuntime?

ANSWER: Do so at your own risk.  It’s like swimming in an unguarded pool or skydiving …

Using the DefaultWorkflowSchedulerService in an IIS host (specifically ASP.NET) is one of those good/bad scenarios depending on point of view.  Windows Workflow Foundation (WF) has no qualms about using the DefaultWorkflowSchedulerService in an ASP.NET hosted scenario and everything will work just fine from a WF point of view.  The problem is that ASP.NET does NOT like people using up all its threads.

Our ManualWorkflowSchedulerService was written specifically for the ASP.NET scenario to make sure that we were running on the minimal number of threads.  The call to RunWorkflow is an explicit “gifting” of the current thread (the request thread in the IIS case) to run as much of a specific workflow instance as possible.  When you introduce the DefaultWorkflowSchedulerService you are, by default, allowing as many as 4 threads to run workflow instances.

Is that a bad thing?  In most cases, no.  Don’t quote me on these numbers, but .NET supports something like 25 threads per processor per Process.  If you are doing anything with Transactions, then at least one of those threads needs to be “available” to avoid deadlock in some cases.  The number of threads ASP.NET requires depends on the situation – if you are running a single web service in an isolated AppPool then I can’t imagine ever running into an issue.

So, what’s the “official word” – the statement that covers everyone’s butt and will hopefully steer users to a design that is free from danger?  

First, examine your scenario.  Ask yourself why you need to be doing the processing in the background (non-request thread)?  Is all processing tied to a request?  Does the processing take very long?  Is new processing ever driven by a “delay” in the workflow or some event not tied to an inbound request? 

If you are doing a lot of processing then it is often better to model this as a windows service.  Using Windows Communication Foundation (WCF) you can directly expose your windows service as a consumable web service.  Alternately you can use WCF or .NET Remoting (last generation technology at this point) to communicate between your current web service and your windows service.

If you aren’t doing much processing and it is all tied to the request, then consider using the ManualScheduler.  While this will add additional latency to your responses, it can be considered a constant value as opposed to the unpredictable response times you’ll see when you’ve got an unknown number of active workflow instances vying for processor time.

In general, try to avoid using the DefaultWorkflowSchedulerService in ASP.NET/IIS.  If you do use it, use it with caution and expect that there may be a few unknown problems which pop up during stress.  There is always an alternate design and in general the tradeoffs will be maintainability/complexity versus request/response speed versus stability under stress.

Comments (19)

  1. bryant says:


  2. sreenin says:

    I have a workflow with 3 activities

    1) Create Customer

    2) Create Education history

    3) Create Job Histroy

    I created new workflow instance and completed step1.

    Next time, depending on workflow activity I need to show either screen1 or screen2.

    FOr that purpose, I want to open workflow and want to know whether "Create Education history" is done or not. How do I know that?

  3. I really like what the on10 guys did with the on10 website. The login UI is the best I’ve seen and I…

  4. If you are using a state machine workflow in ASP.NET you need to use the ManualSchedulerService. …

  5. ntalbert says:


    We’re currently working on several solutions to the problem that you describe above (essentially a style of Page Flow).   Since all of these solutions are currently internal and still being polished, we don’t have any public guidance.  I can, however, give you the generic design for WF applications in which data from the workflow needs to be queried.  Note that any time I mention a database below I mean any store (file, memory, etc).

    WF Apps with Data Query
    A WF application is usually composed of several parts, only one of which is truly the WF component – a workflow defining some process.  The other components often include visualization, storage of data, generic query ability, and sometimes the mechanism by which human work can be completed.  In this vein, a common pattern is the WF workflow as database writer and application as database reader.

    Application——–> WorkflowRuntime ——-> MyWorkflow
       ^                                                                     |
       |                                                                      |
       —————  Database <————————-

    In this pattern, something is done on in the application which causes an event to be raised to the workflow.  The workflow processes the event and, if it causes some change to data, writes the change to the database.  The application, in turn, always queries the database to get information.

    Let’s say we have a document review process.  I might submit a document which would cause the workflow to put the document in a shared folder and update the database with tasks for several users (reviewers).  Some application will be driven by the database to inform users of the tasks (or maybe an e-mail was sent from the workflow).  Once a review is complete, the user will submit feedback which, again, causes the workflow to process the feedback and update the database (remove the task for that reviewer).  When all reviews are complete (as determined by the workflow), the workflow will continue to process the document whether this means adding a task for the person who submitted the document, uploading the document programmatically, or any other set of steps.

    Mapping to Your Scenario
    In your scenario you would query the database to see which “step” you are currently performing and show the appropriate screen for that “step”.  The workflow would manage the process behind the steps as well as the processing of the data associated with completion of a step, but it would be up to the application’s querying of the database to discover what to display to the user.

    Alternate Solution
    The StateMachineWorkflow supports a type called StateMachineWorkflowInstance.  I do not have much experience with this type, but I believe it has a member called CurrentState which will tell you the state of the workflow.  If you can map your workflow to a state machine, then you can use this data to determine the current page to display.

  6. snesbitt76 says:


    I’m very interested in exploring the following paragraph in your blog:

    "If you are doing a lot of processing then it is often better to model this as a windows service.  Using Windows Communication Foundation (WCF) you can directly expose your windows service as a consumable web service.  Alternately you can use WCF or .NET Remoting (last generation technology at this point) to communicate between your current web service and your windows service."

    Our requirement is to build scalable workflow apps using an SOA model.  We want to be able run many instances of long-running workflows of different types.  The workflows will generate human tasks which will be rendered and actioned through our existing user interface.  We currently have a BizTalk implementation in which the worklfow map is encoded.  We use web services to communicate between the workflow and the interface code.  We are looking to WF to make our workflow definition more flexible and easier to develop.  So far I’m very impressed with WF and eager to take advantage of it.  I have been researching WF hosting and communication options for the past week and am trying to figure out the best model to follow.  Initially, I was looking at running my workflow in a web service (to follow loosely our current model), but the threading and runtime issues seem to complicate things.

    Based on the paragraph I quoted from your blog, you mention the ability to run the workflow from a windows service yet expose it via a web service.  This seems like a more robust model.  Do you have any tips or code samples on how I would go about this?  Based on my requirements do you agree this is a good direction?  Looking ahead I may want to scale the workflow across a server farm, but for the time being I’m happy to have multiple web application servers communicating with a single server that hosts the workflow.

    In any case,  I’d really value your opinion.  I have gathered a lot of useful information from your blog, so thank you very much.

    All the best


  7. ntalbert says:

    snesbitt76, I hate to get all “in theory” on you, but I assume you’d appreciate an answer as opposed to a “I’ll try to get to that at some point.”  In short, I’ve never actually done any of the things I’m about to talk about, but they should all work “in theory.”


    First, here are some links for WCF data:

    If you search for “windows communication foundation” you will find many, many additional resources including blogs, samples, and MSDN articles.

    WCF Windows Service Web Service

    Now, it is my understanding that creating a Windows Service and exposing it as a web service through WCF should be easy as pie.  Since this is the first part of the project, let’s look at the steps:

    1. Create a WCF attributed interface which will define your web methods.  Just write your interface and then add the appropriate ServiceContract and OperationContract attributes.  The above resources will have samples that will get you up to speed VERY quickly on how to apply these attributes. 
    2. Write your class which implements the interface.  We’ll discuss the implementation of the methods below because this ties very closely to the workflow aspect of the project. 
    3. Write your windows service.  The OnStart method should create and open a new ServiceHost for your implementation type.  The OnStop method should clean up the ServiceHost. 
    4. Create an application configuration file for your windows service.  This app.config should specify a wsHttpBinding (once again, see resources above for details) with a valid URI.

    Now, if you load up the windows service and start it you should be able to point wsdl.exe at the URI you specified and get a proxy just like you would with any other web service.  For a simple interface, one with a HelloWorld kind of method, you should be able to get through the above 4 steps with about 40 lines of code (mostly curly braces) and a few lines of config file.

    Communicating with the Workflow

    Now, to flesh out the service code.  You’ll need to decide how you want to raise events into your workflow.  WF has three real options here:
    1) ExternalDataExchangeService
    2) WebServiceInput/WebServiceOutput
    3) Custom communications using WorkflowQueue

    (2) on that list is out of the question because that is designed to work closely with our WebHostModule when hosting inside ASP.NET.  That leaves us with (1) and (3).  This is a matter of personal preference and, depending on your exact scenario, you might find one to be better than the other (get more for free).  Feel free to ask about the options, but for now we’ll just say that you’ll have to pick some way to communicate data into (and get data out of) the workflows.

    So, for each method on your service you’ll send data into the correct instance (note that instance correlation will be your responsibility regardless of communication option chosen).  If the method has a return value then you will wait for the workflow to send some data back out (usually through a service added to the WorkflowRuntime) before returning the value.  Done and done.

    Knobs to Turn

    • WCF provides different “instancing” modes for its services.  Each one corresponds to a different pattern you might want to use in your overall architecture.  For example, if your “conversations” with a specific workflow instance are long lived, then it doesn’t make sense to tie the workflow to a specific “session”.  Instead, you can use InstanceMode.Singleton which will cause one instance of your service to generically handle inbound calls to the web service.  If, however, your workflow’s were short lived and a client would make several quick calls to the same instance before the instance completed, then it would make sense to use InstanceMode.Session.  This will create a service instance when a client first connects and reuse that instance for the rest of that client’s conversation.
    • Where the WorkflowRuntime is hosted is also up to you.  You could host the runtime in the Windows Service (start and stop it in the OnStart and OnStop) and have the WCF service(s) interact with that WorkflowRuntime.  You could also host the runtime inside your WCF service itself.  Note that you should be careful about the latter option in the InstanceMode.PerCall (I think that is what it is called) as you will have WorkflowRuntimes being started and stopped all the time since a new service instance is used for each call.
    • Unless you have shortlived, session based, workflows, in order to correlate an inbound call to a specific workflow instance you have to pass an identifier with the message in some way.  Sometimes it makes sense to just pass the Guid WorkflowInstance as a parameter to the call.  Other times it makes sense to save a mapping between key tokens in the inbound data and the instance that will run.  Still other times it makes sense to keep track of the instance ID at a lower level – like in the SOAP headers or as an additional peice of data tacked on to any message.  WCF provides extensibility points all along the message processing pipeline on both sides of the wire which allow you to insert and extract such data.  What you use is up to you, but this provides for some very elegant solutions.
    • WF allows the user to plug in a custom scheduler service giving complete control over the threading model.  If your scenario has two-way web service operations (methods have return values) then you’ll want to consider latency issues.  Most workflows are idle 95% of the time, but if you are writing processing intensive workflows, then our out of box default scheduler service will hurt you.  By default, our scheduler runs at most 4 workflows simultaneously.  These workflows own their respective threads until the workflow goes idle meaning that if you had 4 “never idling, never ending” workflows running and a request came in for one that was NOT currently running, that request would never be handled.  That is an extreme (and contrived) case, but I just wanted to make sure that you consider the effect this can have on latency … let’s say our 4 workflows are “occasionally idling, sometime ending”.  Now if a request comes in for a fifth workflow there could be a bit of a wait before the request is processed with the default scheduler.

    WF, Server Farms, and BizTalk

    Last, but not least, I want to point out that WF is a framework for building applications and not an out of box enterprise solution like BizTalk.  Can you build a BizTalk like solution on top of WF?  Yes, but that will require that you do a LOT of work.  Consider the server farm issue with out of box WF services…

    Imagine that we have two machines, A and B, hosting the WorkflowRuntime and pointing to a shared database for persistence.  Let’s say that a request comes in on machine A which belongs to Instance1.  Machine A will load Instance1 from the database, lock it, and start processing Instance1.  Imagine now that a request comes in on Machine B for Instance1 while Machine A still has the lock.  Machine B will get an exception when it tries to load Instance1 because it is owned by another runtime.

    There are obvious solutions to this problem – send all requests for Instance1 to Machine A every time, or send all requests for Instance1 to the machine which currently has it loaded, or don’t share your persistence service, or have Machine B keep trying to fulfill the request until it doesn’t get an exception.  The thing is that regardless of how you want to solve the problem, it is up to you to solve the problem.

    In conclusion, when you mention wanting “to scale the workflow across a server farm” I just want you to know that it does not come for free.  You will need to determine some architecture for routing the data such that you don’t have multiple machines trying to work on the same instance at the same time (BizTalk’s is called the message box).  Once you determine your architecture it will be up to you to implement it which often means writing custom extensions to our services.

    The End

    From what I’ve seen so far there isn’t anything that WF cannot do.  Whether it is the perfect tool for the job is a different question.  The overview you’ve given me of your scenario seems like a great match for WF as long as you are willing to invest the time in the scalability aspects.  Using WCF will give you great flexbility in your hosting implementation as well.  Let me know if there are any other questions I can answer.

  8. snesbitt76 says:

    Thank you very much for taking the time to reply.  You’ve given me a great deal of information to absorb and ideas to try out.  I will take what you’ve given me and run with it for a few days and see what I can put together.   I’ll probably take you up on your offer to help with further questions.  In any case I’ll let you know when I have something solid working and will share my findings.

    Thanks again!

  9. Guy Barrette says:

    If you’re using state machine workflows in a ASP.NET app, make sure you use the ManualWorkflowSchedulerService…

  10. kwaazaar says:

    Very interesting article which addresses several issues I currently need to solve.

    I’m planning on using WCF for my services and use WF for the actual implementation of the service-logic.

    I created a service-behavior to add an extension to the servicehost which loads a workflow runtime. I can now add this behavior either by configuring it in the application config or by using an attribute on the service implementation class (I’ll add this behavior+code to my blog soon).

    However, I use the extension as a container for my workflow-runtime: when the extension is created, it also creates the WF-runtime and keeps a hold of it in a private field. Since this is all executed within IIS, I also get the drawbacks from running WF in IIS. I could ofcourse self-host my WCF-service in a Windows-service, but then I loose all the advantages I get from IIS (queing, buffering, apppool-recycling, etc).  Therefore I’m thinking of modifying the extension to retrieve a reference to the WF-runtime from a running windows-service instead. This way the extension still works, my WCF-service is still host-agnostic and I’m no longer limited by the threading-issues that were introduced by IIS.

    I’m not sure if this is all going to work or if there’s anything I;ve overlooked? So if anyone has some tips, just let me know!

  11. dawit says:

    i need some help here.. I am using Sequential workflow in an page and I use ManualWorkflowSchedulerService. At one of the states I have included a delay activity. My code gets to the point where it initializes the delay event timer and then nothing happens. It is like the delay timer if off on its own thread and is lost to oblivion with out nothing happening after that in that workflow instance. is there some known issue with WWF and this delay activity class, or do I need some serious reading ??