Hi,
I need to develop an application which performs a data transfer one data base to another. I can not use DTS as a solution due to the complex requiremtns of the application. This application needs to run every 30 secs. So I decided to go for windows service. I am new to windows serivces and multithreading. I have developed an application design and would like to get feed back on it.
General over view of the design :
Application contains the following classes - AccountCreationDTS (WInService class), DTSTimer, DTSController, DTSREquestBin and DTS. AccountCreationDTS.OnStart() starts the DTSTimer. DTSTimer._onTimeElapsed() invokes DTSController.startTask() which initiates a DTS.
The code for all the classes is given below :
////////////////////////////////AccountCreationDTS///////////////////////////////////
using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.ServiceProcess;
using System.IO;
using System.Text;
using System.Threading;
using System.Timers;
namespace WinService
{
public class AccountCreationDTS : System.ServiceProcess.ServiceBase
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.Container components = null;
private DTSTimer _dtsTimer = null;
public AccountCreationDTS()
{
// This call is required by the Windows.Forms Component Designer.
InitializeComponent();
// TODO: Add any initialization after the InitComponent call
}
// The main entry point for the process
static void Main()
{
System.ServiceProcess.ServiceBase[] ServicesToRun;
// More than one user Service may run within the same process. To add
// another service to this process, change the following line to
// create a second service object. For example,
//
// ServicesToRun = new System.ServiceProcess.ServiceBase[] {new Service1(), new MySecondUserService()};
//
ServicesToRun = new System.ServiceProcess.ServiceBase[] { new AccountCreationDTS() };
System.ServiceProcess.ServiceBase.Run(ServicesToRun);
}
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
components = new System.ComponentModel.Container();
this.ServiceName = "Servicename";
}
/// <summary>
/// Clean up any resources being used.
/// </summary>
protected override void Dispose( bool disposing )
{
if( disposing )
{
if (components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}
/// <summary>
/// Set things in motion so your service can do its work.
/// </summary>
protected override void OnStart(string[] args)
{
// TODO: Add code here to start your service.
this._onStartService();
this._dtsTimer = new DTSTimer();
this._dtsTimer.start();
}
/// <summary>
/// Stop this service.
/// </summary>
protected override void OnStop()
{
// TODO: Add code here to perform any tear-down necessary to stop your service.
this._dtsTimer.stop();
this._onStopService();
}
private void _onStartService()
{
//servivce start up
}
private void _onStopService()
{
//service shutdown
}
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////DTSTimer///////////////////////////////////////////////////
using System;
using System.Timers;
using System.IO;
using System.Text;
using System.Threading;
using System.Collections;
namespace WinService
{
/// <summary>
/// Summary description for ServiceTimer.
/// </summary>
public class DTSTimer
{
public System.Timers.Timer _timer;
private DTSController _dtsController;
public DTSTimer()
{
this._timer = new System.Timers.Timer();
this._timer.Elapsed += new ElapsedEventHandler(this._onTimeElapsed);
this._timer.AutoReset = true;
this._timer.Interval = 30000;
this._dtsController = new DTSController();
}
public void start()
{
this._timer.Start();
}
public void stop()
{
this._timer.Stop();
this._dtsController.shutdown();
}
private void _onTimeElapsed(object sender, ElapsedEventArgs e)
{
this._dtsController.startTask();
}
}
}
///////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////DTSController///////////////////////////////////////
using System;
using System.Timers;
using System.IO;
using System.Text;
using System.Threading;
using System.Collections;
namespace WinService
{
/// <summary>
/// Summary description for DTSController.
/// </summary>
public class DTSController
{
private DTSRequestBin _requestQueue;
private DTSRequestBin _runningQueue;
public DTSController()
{
this._requestQueue = new DTSRequestBin();
this._runningQueue = new DTSRequestBin();
}
public void shutdown()
{
if(this._runningQueue != null && this._runningQueue.Count > 0)
{
foreach(DTS dts in this._runningQueue)
{
if(dts != null)
{
dts.shutdown();
}
}
this._runningQueue.Clear();
this._runningQueue = null;
this._requestQueue.Clear();
this._requestQueue = null;
}
}
public void addToRequestQueue(DTS dts)
{
if(this._requestQueue != null)
{
int nPendingRequests = this._requestQueue.Count;
if(nPendingRequests > 3)
{
return;
}
this._requestQueue.add(dts);
}
}
public void startTask()
{
this._createDTSRequest();
this._startTask();
}
private void _startTask()
{
if(this._runningQueue.Count > 0)
{
return;
}
DTS dts = null;
if(this._requestQueue != null && this._requestQueue.Count > 0)
{
dts = this._requestQueue[0] as DTS;
this._requestQueue.remove(dts);
}
else
{
dts = new DTS();
}
if(dts != null)
{
dts.DTSCompleted += new DTSCompletedEventHandler(onDTSCompleted);
this._runningQueue.add(dts);
dts.execute();
}
}
private void _createDTSRequest()
{
DTS dts = new DTS();
this._dtsController.addToRequestQueue(dts);
}
private void onDTSCompleted(object sender, DTSCompletedEventArgs e)
{
DTS dts = sender as DTS;
if(dts != null)
{
this._runningQueue.remove(dts);
}
}
}
}
///////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////DTSRequestBin/////////////////////////////////////
using System;
using System.Collections;
namespace WinService
{
/// <summary>
/// Summary description for Tak.
/// </summary>
public class DTSRequestBin : CollectionBase
{
private ArrayList _bin;
public DTSRequestBin()
{
}
public void add(DTS dts)
{
this.List.Add(dts);
}
public void remove(DTS dts)
{
if(this.List.Contains(dts))
{
this.List.Remove(dts);
}
}
public DTS this[int index]
{
get
{
if(index <= 0 && index < this.List.Count)
{
return this.List[index] as DTS;
}
return null;
}
set
{
if(index <= 0 && index < this.List.Count)
{
this.List[index] = value;
}
}
}
}
}
///////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////DTS///////////////////////////////////////////////////////
using System;
using System.IO;
using System.Text;
using System.Threading;
namespace WinService
{
public delegate void DTSCompletedEventHandler(object sender, DTSCompletedEventArgs e);
/// <summary>
/// Summary description for DTS.
/// </summary>
public class DTS
{
private volatile bool _continueExecution = true;
private volatile bool _running;
private Thread _currentThread;
public event DTSCompletedEventHandler DTSCompleted;
public DTS()
{
}
public void execute()
{
if(this._running)
{
return;
}
if(!this._running)
{
this._running = true;
}
this._currentThread = new Thread(new ThreadStart(this._performDTS));
this._currentThread.Start(); //started on a new thread so that shutdown can interrupt it in case of a service shutdown.
}
private void _performDTS()
{
try
{
foreach(itemtobetransferred)
{
if(!this._continueExecution)
{
break;
}
//perform data transfer.
}
}
finally
{
if(!this._continueExecution)
{
}
else
{
this.OnDTSCompleted(new DTSCompletedEventArgs());
}
this._running = false;
}
}
public void shutdown()
{
try
{
this._continueExecution = false;
this._currentThread.Join();
}
finally
{
}
}
protected void OnDTSCompleted(DTSCompletedEventArgs e)
{
if(this.DTSCompleted != null)
{
this.DTSCompleted(this, e);
}
}
}
public class DTSCompletedEventArgs : EventArgs
{
public DTSCompletedEventArgs()
{
}
}
}
/////////////////////////////////////////////////////////////////////////////////////////////////
Any comments and suggestions about the design and use of windows service model would be highly appreciated.
Thanks in advance
Shameer

.NET data trasfer application architecture - windows service
Jemau
Shameer,
why don't you explain in one or two sentences per class what responsibility the class has
ShadowRayz
While DTS might not be enough for your needs - I suggest you take a look at its SQL 2005 incarnation, namely SQL Server Integration Services (SSIS) which is much more powerful
Arnon