Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / C#

Writing an Extensible Polling Service

4.43/5 (3 votes)
23 Aug 2010CPOL5 min read 30K   404  
Windows polling service with configurable add on tasks

Introduction

This article discusses how to design and develop a Windows polling service that is flexible enough to allow the addition of new tasks in the future.

There are two main parts in this article, the task configuration and creation and execution of these tasks.

This also makes for a good tutorial on how to setup a custom configuration section using Configuration Section Designer and on using the system timer class to poll in a Windows service.

Background

In an enterprise system environment, you often come across the need to execute asynchronous processes/tasks. The most common approach is to create a Windows service that will poll for tasks and execute them. However, this leads to the creation of a number of services over time.

Managing multiple services and ensuring that they are all up and running can be a huge task by itself. Not to forget the development time involved in rewriting the same polling service code every time. This led me to build a generic polling service that could run any task in an orderly manner and be flexible enough to allow for the addition of new tasks with relative ease in the future.

Prerequisites

You will need to download and install the Configuration Section Designer from CodePlex.

Using the Code

This first part describes how to create a configuration section dedicated to configuring tasks. The Configuration Section Designer tool is a nifty little tool that allows you to do much of the heavy lifting easily and I highly recommend it.

Configuration Section

First, we need to create a configuration section to deal with configuring the individual tasks.

Once you create your project, you will need to right click on the project in the Solution explorer and click on the Add New Item.

This will bring up the Add New Item dialogue box. For a default installation of Configuration Section Designer tool, you should be able to choose ConfigurationSectionDesigner template as illustrated below:

VsAddNewItem.JPG

Designing the Configuration Section

Once you have the designer open, you will need to create a Configuration Element by dragging the Configuration Element icon from the Toolbox. Right click on the newly created Configuration Element on the designer and choose Properties from the context menu. Then enter the following properties in the same way as creating the Configuration Section above.

Name - Task
NameSpace - WSPolling

Add the following attributes to the Configuration Element in the same way as creating the Configuration Section above.
* Please note that the XML Name is case sensitive.

Name Type Xml Name IsKey
TaskName String taskName True
TaskOrder Int32 taskOrder
Enabled Boolean enabled

Then we need to add a Configuration Element Collection in much the same way as above you can set the properties for the Configuration Element Collection.

Name - Tasks
Namespace - WSPolling
Xml Item Name - task 
Item Type - Task

Then we need to add a Configuration Section from the toolbox. In the same way you defined the properties for the Configuration Element, right click on the newly created configuration section element on the designer and choose Properties from the context menu.

In the Properties window, set the following properties:

Name - TaskConfiguration
Namespace - WSPolling
XML Section Name - taskConfiguration

* Please note that the XML Section Name is case sensitive.

Then you need to create an element under Configuration Section and set the following properties.

Name - Tasks
Type - Tasks 
Xml Name tasks

The end result of all the configuration should look like the below illustration:

Configsection.JPG

The following code creates a Windows polling service that loads, sorts and executes the various tasks and their attributes.

Required Classes

  • ITask – The interface that defines the individual task
  • TaskManager – The object that loads, sorts and executes the various individual tasks
  • Task1 - Implementation of the task
  • Task2 - Implementation of the task

Create a System Timer

We make use of the System.Timer class to fire events at regular intervals to perform the polling action of the Windows service. You can configure the timer to fire at any given time span - here it is set at 4 secs. First, we instantiate an object of type TaskManager. Then we load all the enabled tasks by looking up the configuration section in the app.config file.

C#
public void runService()
{
TaskManager tm = new TaskManager();
tm.LoadSortedProviders();

aTimer = new System.Timers.Timer(4000);

this.aTimer.AutoReset = true;

// Hook up the Elapsed event for the timer.
aTimer.Elapsed += new ElapsedEventHandler(tm.ExecuteTasks);

aTimer.Start();
GC.KeepAlive(this.aTimer);
} 

TaskManager

This object manages how we load and execute the tasks. This object contains two main methods.

The LoadSortedProviders method loads all tasks configured under the config section TaskSettings and then sorts them by TaskOrder. You can add any additional behaviour you may require in this method.

C#
public void LoadSortedProviders()
{
try
{
foreach (Task tc in config.Tasks.OfType<Task>())
{
ITask t = Activator.CreateInstance(Type.GetType(tc.TaskName)) as ITask;
t.TaskOrder = tc.TaskOrder;
t.Enabled = tc.Enabled;
if (t.Enabled)
{
_cprovider.Add(t);
}
}
_cprovider.Sort(new TaskPriorityComparer());
}
catch (Exception ex)
{
}
}

ExecuteTasks method executes each task from the ordered tasklist.

C#
public void ExecuteTasks(object source, ElapsedEventArgs e)
{
try
{
foreach (ITask t in _cprovider)
{
t.Execute();
}
}
catch (Exception ex)
{
}
}

Task1/Task 2

These classes contain the actual task implementation. You can extend the polling service by adding classes that implement the ITask interface and adding the task implementation within the Execute method of the Task class. They also need to be configured in the .config file as detailed in the below Task Configuration section:

C#
public void Execute( )
{
    Console.WriteLine("Executing task1");
}

Task Configuration

Every task that is added will require the following configuration to be setup in the config file.
taskName is the fully qualifying name of your Task object including the namespace, enabled will determine if it is to be run or ignored when the polling service is started, taskOrder attribute will determine what order the task is executed in. You can add more attributes for your customized requirements.

XML
<tasks>
  <task taskName="WSPolling.Task1" enabled="true" taskOrder="0" />
  <task taskName="WSPolling.Task2" enabled="true" taskOrder="1" />
</tasks>

Points of Interest

One of the things that I would like to do is try and run these tasks in their own memory space so that they don’t create any dependencies on each other. That is, if any of them does crash, I would like to see the others continue to run.

System.Timer class will execute the event on a thread that is obtained from the ThreadPool.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)