Practical .NET

Windows Workflow and Timeouts

Workflows make it easy to do something that's very hard to do in any other development environment: Take action when something doesn't happen. Here's how to protect yourself when something's isn't happening in your Windows Workflows.

In an earlier column, I pointed out that not all processes have response times measured in seconds; some processes  have response times measured in hours, days or even weeks. Those processes issue a call to some other process (typically requiring human processing), and wait for a callback with the results from the other process (or just a signal that the other process is complete).

For those kind of long-running processes, I described how to use Windows Workflow (WF) to create Web Services that automatically handle having to wait. But what if you don't get that response? How will you know when your workflow is stalled? With WF, sending a notification when something doesn't happen is not only easy to do, but also easy to customize.

Playing Defense and Offense
There are two ways to address this problem: defense and offense. Defense means having your workflow, before every activity where the workflow might get stalled, log the activity it's about to perform. As part of the log record, you should include some set of information (information that everyone involved will know) that will allow you to select all the log entries for any particular instance of a workflow. When logging activities in a vacation request workflow, for instance, you might use a combination of the ID for the employee requesting the vacation and the vacation's requested start date to identify any instance of the workflow (presumably no single employee would simultaneously submit two requests for vacations starting on the same day).

Logging the activity if you're working in SharePoint is easy: you have access to built-in logging and email Activities. If you're not working in SharePoint, this might be the time to create a custom activity that you can use to send email. If you're doing that, consider creating a service with methods to accept notifications from your workflows and handle them appropriately; this lets you centralize logging and messaging for all your workflows.

Now, when someone notices that an instance of the workflow has stalled, you can use your log file to determine the last activity performed. That should, in conjunction with some documentation on the workflow's design, allow you to determine why the workflow's stalled. In my experience, it's very difficult to do too much logging in your workflows.

In the same vein, after every activity, you should also send status e-mails to the person most interested in the successful completion of the workflow (for the vacation request workflow, that would be the person requesting the vacation). That person is most likely to notice if the emails stop coming, because the workflow is no longer moving towards its conclusion.

Timeout Notifications
But the fundamental problem is that you really want to send a notification when something doesn't happen -- when an activity that should be performed has gone too long. Essentially, you want to introduce the concept of "timing out". A timeout is "something that happens" when something else doesn't happen. WF makes it easy for you to create the timeout.

As an example, I created a WCF Workflow Service Application project. A Workflow Service starts with two activities already included: A Receive Activity that accepts requests from clients ("consumers", in SOA-speak) and a SendReply Activity that returns an acknowledgment to the client that the request has been received and the workflow started. In one of these Activities, you should log that an instance of your workflow has started. At the end of the workflow, you'll need to add a SendAndRecieveReply Activity that will call some service at the client to return the result from the workflow. In the RecieveReply Activity, you'll log the successful completion of your workflow (you can't do enough logging).

For any "stallable" workflow task, drag in a Parallel Activity, then drag two Sequence Activities into it. WF will automatically set up the Sequences up as tasks to be performed in parallel. You'll put the Activities that make up your workflow task in one Sequence; in the other Sequence, you'll define your timeout. Before the Parallel Activity, log that you're entering the task, and after the Parallel Activity send a status email to the interested party.

The first thing to handle is the scenario when your tasks Sequence finishes in a timely fashion. When that happens, you'll want to terminate the timeout Sequence. To support that, right-click on the Parallel Activity and select Create Variable. In the variable list that pops up, add a new variable of type Boolean, and set its default value to False. Then drag an Assignment activity to the end of the Sequence that holds your workflow tasks. In that Assignment Activity, set your timeout variable to True so that, when your workflow tasks complete, your timeout Sequence will be quietly wrapped up.

In the Sequence that will handle the timeout, add a Delay activity as the first activity and set its Duration for the amount of time you're willing to wait for your tasks Sequence to complete as a timespan. If you're willing to wait one day, for instance, you'd enter this:

New Timespace(24,0,0)

Following the Delay, add a log Activity to post a notification that that task timed out.

Timeout Customization
Now you get to customize your timeout. You may want to terminate the Workflow if the task times out -- if so, drag a TerminateWorkFlow activity into the Sequence after the logging activity.

You may just want to use the timeout notification to tell you that the task wasn't performed and continue on to the next set of tasks in the workflow. If so, add a duplicate of the Assignment activity that sets your timeout variable to true after the logging activity; when time runs out, it will be your workflow Sequence that's quietly wrapped up.

Alternatively, you may just want to nag someone about responding to the workflow sequence and continue to wait for the workflow sequence to complete. In that case, put your Delay and a logging activity in a Sequence inside a DoWhile Activity that has a condition that will never be true. You'll get your notification that the workflow Sequence hasn't completed at regular intervals until the workflow sequence completes (at which point, your timeout sequence will automatically be wrapped up).

You can do more: adding code to your Delay will let you set the duration dynamically at runtime, for instance. But by using WF, you have all the tools you need to take action when something doesn't happen.

About the Author

Peter Vogel is a system architect and principal in PH&V Information Services. PH&V provides full-stack consulting from UX design through object modeling to database design. Peter tweets about his VSM columns with the hashtag #vogelarticles. His blog posts on user experience design can be found at http://blog.learningtree.com/tag/ui/.

comments powered by Disqus

Featured

  • Creating Reactive Applications in .NET

    In modern applications, data is being retrieved in asynchronous, real-time streams, as traditional pull requests where the clients asks for data from the server are becoming a thing of the past.

  • AI for GitHub Collaboration? Maybe Not So Much

    No doubt GitHub Copilot has been a boon for developers, but AI might not be the best tool for collaboration, according to developers weighing in on a recent social media post from the GitHub team.

  • Visual Studio 2022 Getting VS Code 'Command Palette' Equivalent

    As any Visual Studio Code user knows, the editor's command palette is a powerful tool for getting things done quickly, without having to navigate through menus and dialogs. Now, we learn how an equivalent is coming for Microsoft's flagship Visual Studio IDE, invoked by the same familiar Ctrl+Shift+P keyboard shortcut.

  • .NET 9 Preview 3: 'I've Been Waiting 9 Years for This API!'

    Microsoft's third preview of .NET 9 sees a lot of minor tweaks and fixes with no earth-shaking new functionality, but little things can be important to individual developers.

  • Data Anomaly Detection Using a Neural Autoencoder with C#

    Dr. James McCaffrey of Microsoft Research tackles the process of examining a set of source data to find data items that are different in some way from the majority of the source items.

Subscribe on YouTube