Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Scheduled Tasks Web Service

0.00/5 (No votes)
23 Nov 2007 2  
A web service that acts as a scheduler for tasks.

Introduction

Let's say for example that you have to calculate the value of some fields in your database every hour from 8am to 8pm, but you don't have full control of the server where your web application is running; this is a common scenario and my project will provide you the tools to make the job possible.

Schedule Tasks for web applications is not always easy. If we have full control of the host server it's not a problem, but sometimes we don't so we cannot do something like, easily create a console application that performs the tasks that we need for our web application, and then add the compiled EXE to the Schedule Task list of the server.

Let me remind you that web applications don't work the same as Windows applications; if we want to keep our web application alive we have to make periodic requests to it.

Background

Here is another Web Based Scheduler � it uses a different approach to solve the same problem. The sample code in this article has all you need to implement and manage your own Tasks and add them to the Scheduler Service.

One of the most important differences with the other article is that this code uses a Web Service so you can integrate with any application, also force the implementation of the Tasks to follow some pattern, because it uses a base class.

Using the Code

The sample code contains 6 projects:

  • CsharpTask, this project contains a sample task writed in C#
  • SchedulerService.Core, this project contains the Task base class, inherited from this class to implement your own Task
  • SchedulerService.Entities, this project contains a Dataset that represents the Scheduled Tasks also contain some constants
  • SchedulerService.KeepAlive, this project is a console application that makes a call to the Web service, run this app periodically to ensure that the Scheduler will be running
  • SchedulerService.UI, this project contains a couple of windows forms, used to manage the Scheduled Tasks running on the web service
  • WS.Scheduler, this is the core of the project, here is implemented all the functionallity needed to run the scheduled tasks

If you just want to use the Service as it is and want to implement your own task:

  • Setup the WS.Scheduler Web Service on your Web Server
  • Create a new Class Library Project in Visual Studio (no matter the language)
  • Add a reference to the SchedulerService.Core project
  • Create you class and make it inherit from the base class Task
  • Implement the three required methods Execute, LogEntry and CancelTask (more about this later)
  • Compile your project and add the DLL file to the bin folder of the Web Service
  • Configure the SchedulerService.UI.exe.config file if needed, this is the app.config of the SchedulerService.UI project. You may have to configure the URL where your Scheduler service is running, the default location is: http://localhost/Scheduler/Scheduler.asmx
  • Run the UI project and add your task
  • Now that your task is ready to run, make periodic calls to your Web Service to keep it alive, you can use the included console application, you have to setup the URL of the web service in the app.config also.

How to Create a New Task

To create a task that can be scheduled in the service you have to create a Class Library Project in the language of your preference, then add a reference to the SchedulerService.Core project, and create your class and make it inherit from the Task base class. Your implementation for the class before you add any custom code must look like this:

C#
using System;
using System.Collections.Generic;
using System.Text;

namespace CsharpTask
{
    class MyTask : SchedulerService .Core .Task
    {

        public override void Execute()
        {
          throw new Exception("The method or operation is not implemented."); 
        }

        public override void CancelTask(string Message)
        {
          throw new Exception("The method or operation is not implemented.");
        }

        public override void LogEntry(string Entry)
        {
          throw new Exception("The method or operation is not implemented.");
        }
    }
}

VB.NET
       
Public Class MyTask
    Inherits SchedulerService.Core.Task


    Public Overrides Sub CancelTask(Optional ByVal Message As String = "")

    End Sub

    Public Overrides Sub Execute()

    End Sub

    Public Overrides Sub LogEntry(ByVal Entry As String)

    End Sub
    
End Class

The only code that you really have to implement is the Execute method for your class. The implementation of LogEntry and CancelTask methods are optional � write the code if you really need it.

It is a good practice to use Try/Catch blocks in your code. The Task class has a property named AbortAfter � this property is used to abort a task if the task has not finished after X minutes. If you are planning to use this feature you will need to implement a Try/Catch block because when the task is aborted it raises a System.Threading.ThreadAbortException. Also, you have to run the RaiseTaskFinishedEvent method after the task has been finished, otherwise the scheduler will not work properly. If you catch an exception in the code, you can use the RaiseTaskExceptionEvent to stop and disable the task while you find the cause of the exception. Here is a complete template for an Execute method:

    C#
    /// <sumary>


    /// Execute method

    /// </sumary>

    public override void Execute()
    {
        try
        {
            //Task Code goes here


            //Raise the finished event

            base.RaiseTaskFinishedEvent(this.TaskID, DateTime.Now);
        }
        catch (System.Threading.ThreadAbortException ex)
        {
            //Do nothing, this exception is thrown when the task  is

            //cancelled

            //But you have to catch this kind of exception, otherwise the 

            //task will not be marked as Aborted

        }
        catch (System.Exception ex)
        { 
            //Raise the exception event

            base.RaiseTaskExceptionEvent(this.TaskID, DateTime.Now,ex);
        }
    }

    VB.NET
    ''' <sumary>

    ''' Execute method

    ''' </sumary>

    Public Overrides Sub Execute()
        Try
            'Task Code goes here


            'Rasie the finished event

            MyBase.RaiseTaskFinishedEvent(Me.TaskID, DateTime.Now)
        Catch ex As System.Threading.ThreadAbortException
            'Do nothing, this exception is thrown when the task  is cancelled

            'But you have to catch this kind of exception, otherwise the

            'task will not be marked as Aborted

        Catch ex As Exception
            'Raise the exception event

            MyBase.RaiseTaskExceptionEvent(Me.TaskID, DateTime.Now, ex)
        End Try
    End Sub

The sample code contains two test classes, VB.NET (in the same project as the Web Service) and C# (in a separated project), both do the same thing: they write some entry to a log file. Also, they have code so you can test the AbortAfter feature. If the task has defined a value it will enter in some infinite loop (of course, just for test purposes).

That's all you need to know to implement your own Task.

How the Scheduler Service Works

I am not going to put detailed information here of how the Scheduler service works, I just will give an overview of some of the code files in the WS.Scheduler project.

The Scheduler Service has the following methods that you can use to manage the service:

    GetTaskList, this method returns a list of all scheduled tasks in the 
                 Service.
    AddTask, this method is used to add a new task to the Scheduler Service.
    DeleteTask, used to delete a task.
    UpdateTaskList, use this method to update the scheduled tasks.
    RunTasksNow, used to run a task now.
    CancelTask, this method stops the execution of a task.
    GetAvailableTasks, return a list of all available classes that inherit
                       from the 'Task' base class. this method will look in
                       all assemblies in the /bin folder of the Web Service.
    KeepAlive, you can call this method to keep the Web Service running.

The Scheduler Service has code inside Global.asax to initialize and handle the Scheduler.

The service uses the Application_Start method to initialize a Threading.Timer object, you can modify the web.config(key="period") to change the default period of time between timer callbacks, but right now the default period is 120000 miliseconds. The minimum value that you can setup is 30000 miliseconds.

The Timer callback (Timer_Handler method) is where the Scheduler checks if there are any task that must be executed. This method also checks if any of the tasks that are running have expired their allowed time of execution as defined by the AbortAfter property of the task.

The SchedulerController.vb is the core of the Scheduler. This class contains the implementations of the methods exposed by the Web Service, also has the code to manage the execution and cancellation of the Scheduled Tasks.

I just want to comment on the following methods:

GetAvailableTasks, this method will check all DLL's and EXE's in the bin folder of the Web Services and will look for classes that inherit from the Task base class. To do this I am using the Assembly class and the BaseType property of the class Type. If you want to change how the Task will behave after it has been finished (if you called the RaiseTaskFinishedEvent method) change the TaskFinished method of the SchedulerController, if you want to change what happens when an exception is thrown (if you are using Try/Catch blocks and you are using the RaiseTaskExceptionEvent method) change the code of the TaskException method in the scheduler controller.

The method SincronizeTaskObjectAndDataRow is in charge of synchronizing the Dataset and the SchedulerController list of Task objects.

Points of Interest

Right now the List of Scheduled Tasks is being stored as an XML file because I wanted to provide a tool that did not require any DB. However, I prefer to store the task list in some Database.

Remember, there is a lot of room for improvement in how to schedule a task, so check and compare the options that you have in the Windows Scheduled Tasks application to see what I mean. In this sample, there is no authetication or security checks, so I highly recomended that you implement some sort of security check. The other thing that you have to implement is the code for cancelling a running task from the UI.

History

VB.NET Code V1.0

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here