Configurable Delay-activity for WF

A while ago I was doing some technical research on WF: While my workflow was waiting for input, it also had to support some kind of timeout functionality. It also had to be possible to configure the duration of the timeout outside of the workflow (eg app.config), without the need to redeploy or restart the workflow.

Being a newby on the WF-platform, I simply expected the out-of-the-box Delay-activity to provide such functionality. I found out that in a Listen-activity containing an input-activity in one branch and the Delay-activity in another would work fine.

I would use the InitializeTimeoutDuration-event of the Delay-activity to read the configured timeout duration from the app.config. I soon found out I would need such functionality in several locations in the workflow, resulting in many code-blocks for each implementation of the InitializeTimeoutDuration-event.

This was obviously getting pretty messy, so I decided to create a custom activity which would derive from the standard Delay-activity, include the load-duration-from-config logic and supply a 'DelayName'-property to specify which configured duration to use. I soon got pretty frustrated when I found out that most out-of-the-box activities where marked 'sealed' (Microsoft: "though we would like make our product as extensible as possible, we had to prioritize where we'd focus this extensibility for this version and we decided to focus at the component model level, instead of on the out-of-box activities"), thus impossible to derive from.

I solved this by creating a composite activity which itself contained a Code-activity to load the duration from config and a Delay-activity which would initialize itself with the loaded duration.

Although this custom activity worked fine and cleaned up a lot of code from my workflow, I soon found out that it didn't work with StateMachine-workflows. In short: the EventDriven-activity in SM-workflow supports just one activity implementing IEventActivity and it must be the first activity. Since I encapsulated it in my custom activity, it would always be a child-activity of custom activity, so it would never be the first activity. For now, I decided to go for the ugly implementation: standard delay-activities, combined with workflow code to load durations from config.

… But my frustration didn't end there! When testing the application, it turned out the standard Delay-activity wasn't flawless! It supported delays up to 47 days, while we needed delays to last up to 4 months. I registered the issue with MS and also created a PSS-call, but because it turned out to be a bug in the .NET framework itself, MS decided to only fix it for the 3.5 framework, leaving me (and my customer) in the dark! 🙁

To get this all over with, I finally decided to create a custom delay activity by implementing the IEventActivity-interface myself. Although the standard Delay-activity could not be inherited from, it could be reflectored! I copied most code, added logic to cut the huge durations into smaller peaces of max. 47 days (the workflow is loaded every 47 days, then unloaded again if the total duration hasn't passed yet). While I was busy, I also included the logic to load the duration from config and finally came up with the Delay-activity that did everything I wanted and supported huge durations!

!!! The above mentioned issue has been fixed since .NET Framework 3.0 SP1 !!!
Check my comment below for more information and how to fix the sample-code!

You can download the source-code for the activity here: RobertKa.Samples.zip
(when downloading the source-code, you are obligated to send me all your useful additions to the code )