Register
Thursday, September 09, 2010
 
 DBAs And ProgrammersBlog
  
News! Minimize
   
 
 Print   
 
Misc Blog Stuff Minimize
   
 
 Print   
 
The Reluctant DBA Minimize
 
 
 
 Print   
 
Reluctant DBA Minimize
   
 
  
 
Reluctant DBA Minimize
   
 
  
 
The Reluctant DBA Minimize
 
Feb12

Written by:CarpDeus
2/12/2009 5:27 PM 

Over the course of my programming lifetime, I've written a fair number of Windows Services applications. And I have found that the easiest way for me to do this is a solution that contains several elements:

  • A class that handles all of the processing
  • A WinForms app to do all of the debugging and testing of the class
  • A Service that replicates the basic implementation of the WinForms app but is a service

So, when tasked with implementing a service that gathers data from a Websphere Message Queue, I thought it would be fairly straightforward. I downloaded the client, went through lots of agony trying to get it installed but finally got that worked out and then turned my hand to writing code. After a couple of hours of flailing around, I got a copy of a code sample that was a console app, which I was able to modify in about 5 minutes to get it doing what I needed it to, which is to take the message in the queue and dump it into a SQL database for further, out of band processing. With that taken care of, how hard could it be to mod this into a service? Well, two days later, the answer is, Not hard at all, but you don't know what you don't know until you realize you don't know it.

To understand why this is so difficult, let's look at some pseudo-code for the meat of the listener:

while(KeepProcessing)
{
  ListenAtQueueForMessageInWaitMode
  GetTheMessage
  ProcessTheData
}

This is the best way to code something like this, just have the listener wait for messages. It's much cleaner than firing off a check every X milliseconds using a timer. Unfortunately, most of my services have done something very like that. On the interrupt, go and do whatever until you're done and then start the timer up to sleep for a bit until it's time to see if there's more to do. Which means my service code looks something like this:

/// <summary>
/// Stop the timer
/// </summary>
protected override void OnStop()
{
// Stop the timer and log
timer1.Enabled = false;
yaNotification("Stopped service");
}

/// <summary>
/// Start a paused service
/// </summary>
protected override void OnContinue()
{
// Base service continuation
base.OnContinue();
// Notify log
yaNotification("Continued service");
// Start timer
timer1.Enabled = true;
}

So my first thought was to simply call the process from within the OnContinue or OnStart. Which basically hung the service in that mode because it never finished the OnStart since it was listening to the queue. So I started working on threading. But it would process one record and die, because it was attempting to pass notification to the handler across threads.

Long story short, I got it to function by moving the messaging into the worker class.

public void ProcessMessages()
  {
   KeepProcessing = true;
   backgroundThread = new Thread(new ThreadStart(GetMessageFromTheQueue));
   backgroundThread.Start();
  }

Now, the service calls ProcessMessages, which returns quickly, and the GetMessageFromTheQueue contains the loop. When I need to stop or pause the service, I simply change the boolean public variable the the loop is looking at and, as soon as GetMessageFromTheQueue processes the next message, it ends.

I suspect I'll be doing more of this type of service soon.

Technorati Tags: ,,,

Tags:

Your name:
Your email:
(Optional) Email used only to show Gravatar.
Your website:
Title:
Comment:
Security Code
Enter the code shown above in the box below
Add Comment  Cancel 
 
 
  
 
Privacy Statement | Terms Of Use Copyright 2001-2008 by ReluctantDBA.com