Once you have the WorkflowRuntime up and running in an ASP.NET application or web service, you'll want handle key life cycle events like WorkflowTerminated and WorkflowCompleted. I want to warn you about some common pitfalls I've seen.
There are two subtle but extremely dangerous problems in the following code.
Think: Singletons and event handling. The WorkflowRuntime will typically be a singleton in an ASP.NET app. In the WF RTM version, you can have multiple WF runtimes executing inside the same AppDomain (this wasn’t true in the betas), but chances are you don't want to pay the performance overhead of spinning up a new WF runtime for each request. Thus, we have a single and globally accessible WF runtime. For questions about the ManualWorkflowSchedulerService, see my article on hosting Windows Workflow. This scheduler allows us to run the workflow instance synchronously - on the same thread as the request.
The WorkflowCompleted event will fire for any workflow that completes, not just the workflow we are executing inside this page (or web request).
Let's say the workflow is running some business rules to automatically approve or reject expense reports. This usually requires a human bean counter to get involved, but stick with me for a second and pretend it's all done in silicon. Let's say the workflow indicates approval or rejection with the OutputParameters property of the WorkflowCompletedEventArgs.
User Joe submits an expense report for his new red stapler. At the same time, I submit an expense report for a red Ferrari Enzo. There are two pages executing on the server, and both subscribed to the WorkflowCompleted event. If things work out just right, Joe's workflow will complete first and approve his expense report. The runtime will raise the completed event, which both pages handle. Since Joe's workflow indicated approval, Joe will soon be stapling papers while I get to go 0-60 in less than 3.5 seconds.
To fire the completed event, the WorkflowRuntime maintains a reference to the Page object. We should assume the WorkflowRuntime, as a singleton, will live for the duration of the AppDomain. Assuming the Page object never un-subscribes from the completed event, it will be in memory for the duration of the AppDomain, too. The garbage collector can't take the Page out of memory while it's being referenced by the WF runtime. RAM will start to disappear over time.
Even worse, with each request another instance of this Page class will wire itself to the WorkflowRuntime, and each time a workflow completes the WF runtime will need to raise the event to all these zombie page objects. This will keep the CPU busy, too.
It won't be long before the server is sucking mud, and the company is out of money.