Skip to content
September 17, 2015 / kiranpatils

One more way to Run Sitecore scheduled task at the same time every day

Challenge:

You would like to Run Sitecore scheduled task at the same time every day. You already did Google Search and came across this article? : https://briancaos.wordpress.com/2011/06/28/run-sitecore-scheduled-task-at-the-same-time-every-day/

But thinking that, Is there any other way to do it? Can you do it with minimal code? And the answer is yes. Eager to know. Let’s have a look at it:

Solution:

There is only one prerequisite to apply this solution. Your scheduled task should be async or you can make it async. If you have heard about async task first time, and have no idea. What we are talking about then no worries, Would suggest you to read following posts :

If you are already running your schedule task async or earlier articles, convinced you that you can do it. Then let’s have a look at it. How we can achieve our main goal.

Let’s see how we can create a scheduled task, Which runs every day at 5 AM

Create a scheduled task, and make sure it runs as per this schedule [Every 24 hours] : 20000101|21000101|127|23:59:00

Your scheduled task should have code like this:

public class BasicTaskCommand
 {
 public void DoSomeBasicStuff(Sitecore.Data.Items.Item[] items, Sitecore.Tasks.CommandItem command,
 Sitecore.Tasks.ScheduleItem schedule)
 {
 try
 {
 // Do some basic stuff -- Your main logic goes here
 }
 catch (Exception)
 {
 // Log error
 }
 finally
 { 
 // Run scheduler at 5 O'Clock
 DateTime? dateTimeToSet = GetSpecificTime(DateTime.Now, "5:00");
 if (dateTimeToSet.HasValue)
 {
 Log.Debug("Setting " + schedule.Name + " .LastRun to " + dateTimeToSet.Value.ToString("f"), new object());
 using (new SecurityDisabler())
 {

 schedule.BeginEdit();
 schedule.LastRun = dateTimeToSet.Value;
 schedule.EndEdit();

 }
 }
 }
 }

 private static System.DateTime? GetSpecificTime(System.DateTime now, string specificTime)
 {
 var parseString = string.Format("{0}/{1}/{2} {3}", now.Month, now.Day, now.Year, specificTime);
 System.DateTime date;
 if (System.DateTime.TryParse(parseString, out date))
 {
 return date;
 }
 return null;
 }
 }

The main magic happens within a finally block. Basically, We are setting LastRun time to the time we want our scheduler to get executed. In this scenario 5 AM.  Which means once Task command has done all the main logic. It will set LastRun to Today’s Date + Specified time. So, next time whenever scheduling agent polls for IsDue or not. It will find it true after 24 hours only. Again, It won’t have dot accuracy. But that was fine.

You must be wondering. Then why this trick doesn’t work with task which is not async? Good question. Basically, When task runs as async. Then on trigger time. It will invoke Command’s execute method. And it will proceed to next code. Which is setting LastRun Time. Now, Our method is doing its defined logic and once it gets completed it will call finally method which again sets LastRun and as this was last change. It wins! This doesn’t happen in sync scenario. Because first your command’s  execute method will get executed, which will perform logic, then set time. And after that Sitecore TaskDatabaseAgent will set it’s LastRun Time. Which will be current DateTime and that will overwrite your change!

Great idea?! If you liked the idea. Then credit goes to Daniel Schoenberg — Who invented/discovered this trick!

If you would like to have granular level of control and accuracy on your scheduled tasks. Then would strongly recommend : https://marketplace.sitecore.net/Modules/S/Sitecron.aspx?sc_lang=en

Happy Scheduling! 🙂

 

Advertisements

2 Comments

Leave a Comment
  1. Sasha / May 11 2016 12:29 pm

    Hi Kiran,

    I get the following:

    ERROR Error executing schedule item: Schedule Item
    Exception: System.InvalidOperationException
    Message: Collection was modified; enumeration operation may not execute.
    Source: mscorlib
    at System.Collections.Hashtable.HashtableEnumerator.MoveNext()
    at Sitecore.Data.DataProviders.Sql.SqlDataProvider.UpdateItemFields(ID itemId, ItemChanges changes)
    at Sitecore.Data.DataProviders.Sql.SqlDataProvider.c__DisplayClass1d.b__1b()
    at Sitecore.Data.DataProviders.NullRetryer.ExecuteNoResult(Action action, Action recover)
    at Sitecore.Data.DataProviders.Sql.SqlDataProvider.SaveItem(ItemDefinition itemDefinition, ItemChanges changes, CallContext context)
    at Sitecore.Data.DataProviders.DataProvider.SaveItem(ItemDefinition item, ItemChanges changes, CallContext context, DataProviderCollection providers)
    at Sitecore.Data.DataSource.SaveItem(ID itemID, ItemChanges changes)
    at Sitecore.Data.Engines.EngineCommand`2.Execute()
    at Sitecore.Data.Engines.DataEngine.SaveItem(Item item)
    at Sitecore.Data.Managers.ItemProvider.SaveItem(Item item)
    at Sitecore.Data.Managers.PipelineBasedItemProvider.ExecuteAndReturnResult[TArgs,TResult](String pipelineName, String pipelineDomain, Func`1 pipelineArgsCreator, Func`1 fallbackResult)
    at Sitecore.Data.Managers.PipelineBasedItemProvider.SaveItem(Item item)
    at Sitecore.Data.Items.ItemEditing.AcceptChanges(Boolean updateStatistics, Boolean silent)
    at Sitecore.Tasks.ScheduleItem.set_LastRun(DateTime value)
    at Sitecore.Tasks.ScheduleItem.Execute()

    Is it just me? How do I overcome it while still having it async?

    Appreciate your answer in advance 🙂
    Sasha

    • kiranpatils / Aug 22 2016 5:21 am

      still looking for help?

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: