Background processing for websites with Task Scheduler

17 Sep 2017

Many websites do some processing which does not necessarily have to be done by the website itself. Things like sending emails and processing orders often do not need to have their results displayed immediately on the web page which initiated them. In such cases, the work could better be performed by some background proces outside of the context of the website. This frees up processing for the website and gives the website user a more responsive experience. It also often keeps the website code cleaner and simpler.

Usage examples

  • Sending out emails for processed orders every few minutes
  • Background processing of order handling
  • Cleaning up database records

Implementation choices

There are al lot of possible implementations of this approach, especially in a cloud environment. Azure for example offers Webjobs and the new Functions. These cloud implementations are in many cases your best choice. But not everyone is able to use them. Many organisations still don't want or can't host their code in the cloud. For such on-premise environments the usual candidate for implementing background processing is a Windows Service. Another option however is running a console app which is started by the Windows Task Scheduler. A console app is in most cases easier to test and simpeler to deploy than a Windows Service. Your console app can be started by the Windows Task Scheduler, for example sending emails to the users of all processed orders of your webshop every 5 minutes. By using the Task Scheduler you don't have to implement scheduling yourself, the Task Scheduler also has its own retry options, another thing the Task Scheduler handles for you. So in most cases where you need a task which needs to be executed on a scheduled base, a console app executed by the Task Scheduler is your best option.

Windows Service

Use cases

  • A service which waits for incoming calls from other services
  • A task which checks the status of a related system with very short intervals (< 1 minute)

Pros

  • Runs continuously
  • Runs in a secure context

Cons

  • Runs continuously so always allocates some resources
  • When you need to execute a tasks on a schedule you have to build the scheduler yourself
  • Difficult to test
  • Relatively difficult to deploy

Console app executed by Task Scheduler

Uses cases

  • Sending emails for every processed order every few minutes
  • Updating a cache store every 15 minutes
  • Running a clean-up task every night

Pros

  • No custom scheduling code necessary
  • Runs only when requested so uses resources only then
  • Very easy to test
  • Easy to deploy

Cons

  • Not suitable for tasks which need to be always active
  • All users with access to the server can execute the task

Deployment of Console app and Task Scheduler

Deployment of the console app itself is as simple as copying the files (.exe, .dll and .config). Most deployment tools have simple options for this. Setting the right options for the Task Scheduler can be done manual through the Task Scheduler UI, but you can also automate this by using Powershell scripts. Your deployment tool can execute these scripts, making the entire deployment an one click action.

Example of Powershell script for creating a Task Scheduler task
    $name = "My Task"
    $user = "####"
    $installRoot = "c:\windows"

    Unregister-ScheduledTask -TaskName $name -ErrorAction SilentlyContinue -Confirm:$false	
    $action = New-ScheduledTaskAction -Execute $installRoot"\notepad.exe"
    $settings = New-ScheduledTaskSettingsSet -MultipleInstances IgnoreNew
    $trigger = New-ScheduledTaskTrigger -Once -At (Get-Date).Date -RepetitionInterval (New-TimeSpan -Minutes 5)
    Register-ScheduledTask -Action $action -Trigger $trigger -TaskName $name -Description "Task to do something usefull" -Settings $settings -User $user

This Powershell script, after setting some variables, first unregisters the task (if it exists) to allow the task to be registered anew, this is usually easier than checking for the existence of the task and if it exists update it. Next an action is defined to execute your console app. Then (as an example) settings are given to not start a next scheduled run when the previous one is still running. Next the schedule (trigger) is defined, here we set it to start at the current Date, and repeat every 5 minutes. Another, simpeler trigger could be $trigger = New-ScheduledTaskTrigger -Daily -At 6am. Finally everything is put together and the task is registered. In most cases your application can best run under the NETWORK SERVICE or LOCAL SERVICE user accounts. If you use a regular user account, take care to set your task to also run if the user is not logged in. In a normal deployment pipeline most variables would of course be set by your deployment tool. For more settings just click through the Task Scheduler UI and see what's available or read the PowerShell documentation. There are a lot of settings here.

Conclusion

For on-premise background work for your website, web application or API, don't automatically start developing a Windows Service. Look at your use case and see if you can safe yourself some work by going for a console app and Task Scheduler. In many cases this is a quicker and easier and more efficient way to reach your goal. Happy programming.