Updating progress in SharePoint timer jobs

What can SharePoint tasks be used for?

Timer jobs are SharePoint mechanism that allows to centrally manage and run tasks related to SharePoint Farm’s infrastructure or Web Applications custom business logic.

Some tasks come out of the box and perform operations like Active Directory synchronization, farm health analysis, processing queued documents with Word Automation Services, etc.

Task can also be created and added programatically when you deploy a solution or activate a feature. Depending on the business scenario, they might for example:

  • Send emails to users
  • Generate daily/weekly reports
  • Synchronize business data with other systems (database, ERP, CRM)
  • Import some data from external system, eg. current exchange rates from a bank service

Monitoring task progress

Task that come out of the box almost always report their progress which can be viewed in SharePoint farm’s Central Administration (or in other ways). Figure #1 presents that view.

SharePoint: monitoring progress of timer jobs

Fig. 1. SharePoint: monitoring progress of timer jobs. Source:
Update SharePoint Timer Job Progress Programmatically

If you want to report a progress from your own timer job, which is always instance of Microsoft.SharePoint.Administration.SPJobDefinition class, you can simply use this.UpdateProgress(int newPercentage); method.

Monitoring task progress might seem to be a feature of a little importance, but it can be useful to see how fast a task progresses, whether it got stuck somewhere, or when it could end if a process is time-critical. It might give some quick insight into what’s going on for developers and other people waiting for the task to finish.

But there are some problems

The method mentioned before might be enough for simple tasks, but if you need to monitor progress of some long-running timer job, you might notice some problems with it:

  • Every time you want to monitor progress of a loop, you must compute a progress yourself
    • and it typically involves dividing integer by other integer, which will give you incorrect result if you forget to cast to float
    • it might also result in exception if you exceed the range of 1-100 by some mistake in calculations
    • you might notice performance degradation, because even if the progress (represented as integer) doesn’t change with every iteration, request is sent to SharePoint server each time you call UpdateProgress()
  • You will either repeat the code like: int newProgress = (int) (loopRangeFrom + (iterationsPassed / allIterations) * ((double)(loopRangeTo - loopRangeFrom))) which doesn’t make the job more readable, or give up updating progress in loops and only update progress on some arbitrary “milestones” in code execution.

So even though it’s very simple, it’s a bit risky piece of code to add as there are few places to make a mistake and it might result in exceptions that may break the timer job.

Making it easier

To simplify reporting progress in loops I created a simple C# class called ProgressUpdater that tries to get rid of all the problems listed in the previous section. Here’s the example usage of this class:

In this case we didn’t have to do any calculations. Instead, we need to specify when the loop starts, how many iterations it’s going to have, what progress the job should have at the end, and call ProgressLoop() after each iteration. If that looks easier, here’s the ProgressUpdater class:

I used the above code many times, and it didn’t have any problems with it (except that it uses API’s that can’t be used in sandboxed solutions). If you find it useful, feel free to copy and use it in your projects, you might modify the code according to your needs.