.NET data trasfer application architecture - windows service

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



Answer this question

.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



  • .NET data trasfer application architecture - windows service