Lijit Search

How to poll a service using a C# Timer

This is a kind of post where I share with you what I learned while solving a problem. Likely you might think of 3 better ways to do this.  If so, please share. I love learning.

The overall goal is to create a Pop3 service utilizing an off-the-shelf Pop3 library to poll one or more email accounts and push all emails found into a business workflow. Here we go.

Separate the code from library specificity

In the past I worked on a similar piece of software and we got burned by tight coupling to the Pop3 library. My goal this time around is to completely isolate the Pop3Service from the library that ultimately does the POP3 protocol icky-ness.  I first wrote a wrapper around the Pop3 library creating a class that simply returns emails.

public interface IEmailGateway
{
IEmailMessage[] GetAll();
}


Doing something repeatedly



Next up we need a service class for polling a list of IEmailGateways at a specified interval. To accomplish this I use the Threading.Timer class which lets you specify a callback to be called on a recurring basis from the thread pool. Excellent. We don’t have to worry about ookie thread management and endless sleeping while loops.



public class Pop3Service 
{



public void Start(Action<IEmailMessage> receiveEmailAction)
{
_receiveEmailAction = receiveEmailAction;
IsStarted = true;

_getEmailTimer = new Timer(TimedEmailRetrieval, null, _waitSpanBeforeInitialEmailRetrieval, _getEmailInterval);
}

public void TimedEmailRetrieval(object notUsed)
{
if (ShouldCheckEmail())
{
RetrieveEmailsFromRepositories();
}
}


But not concurrently



My testing quickly ran into an issue when retrieving emails. If you set the Timer interval to be so short that next timer fires before the current one completes, multiple threads will be hitting the Pop3 server. Besides being bad behavior I found out that my integration email server (hMailServer) didn’t let like this.



To solve this I added some synchronization and updated email retrieval to do nothing when email is already being retrieved.



private void RetrieveEmailsFromRepositories()
{
lock (_locker)
{
_isCheckingEmail = true;

foreach (var emailRepository in _emailGateways)
{
foreach (var emailMessage in emailRepository.GetAll())
{
_receiveEmailAction(emailMessage);
}
}

_isCheckingEmail = false;
}
}

private bool ShouldCheckEmail()
{
return IsStarted && !_isCheckingEmail;
}


Testing for potential concurrency problems is tricky. From what I can see the worst case scenario for this code is that back to back email retrievals get executed.

A Tale of Two Installations

One of my pet peeves about working on Windows is that there is no built in software update system. You can get your officially blessed Windows security updates automatically, kudos to Microsoft, for that but I want the same thing standard for every piece of software I have installed on my PC.

This morning I was interested in playing around with Ruby. Let’s compare installing a ruby interpreter on Windows to Linux.

Windows Installer Ghetto

Let’s document the steps involved in getting Ruby onto a Windows system the One Click Ruby Installer for Windows.

  • Google for the website of the software download.
  • Download their installer.
  • Run the installer.
  • Click Next.
  • Ok the EULA.
  • Choose the components. What are these things?
  • Click Next.
  • Choose a directory. Hmm do I really want it installed to my drive’s root? 
  • Click Next.
  • Pick a start menu folder. Why give me a choice?
  • Click Install
  • No I don’t want to view the readme.
  • Click Finish.

I cannot believe that the fine people in the Ruby community have the gusto to name this installer One Click. I am pretty sure that title is tongue in cheek. I counted a minimum of 8 clicks not including the installer download. Yuck. Sadly I am sure most Windows users are familiar with this installation ceremony.

Let Me Get That For You

Outside the big blue sphere to install some software you usually just fire up what’s called a package manager and badda boom you get the latest version dropped on your system. According to the Ruby download page here are your potential pain-free vectors of Ruby infection.

Linux (Ubuntu or Debian based distributions)

% sudo apt-get install ruby irb rdoc

Mac OS X

% port install ruby

Solaris

% pfexec pkg install SUNWruby18

 

Open a console and after one command line + administrator password prompt you are pretty much done. The package manager figures out what dependant packages you need to allow ruby to live on your system, downloads them from a trusted repository and installs them. It is very easy and if you are command line challenged there are plenty of GUIs to keep you out of the console.

The More You Know

The package manager problem has been solved by other OS distributors. It should be pretty easy for Microsoft put their weight behind this problem. Take 10-20 engineers and put together a comparable Windows based package manager but this will only work if you get both open and closed source software developers on board.

The open source people will take to it like fish to water. The closed source people will be a hard sell. There will be many hurdles to convince software vendors to get with the program but here is where Microsoft can use their formidable marketing and developer prowess to move the market and raise the level of user experience.

The Successful Programmer’s Spreadsheet

Doing more with less is an important part of the value of software. We write software to enrich peoples lives and quite often that involves automation of annoying repetitive tasks. I am sure that quite a few business people would agree that they love their spreadsheets. Finance tools like spreadsheets liberate the business owner to do things like run their business.

Automation is key for the liberation of the successful software developer.

Free yourself up to do more important things like making better software. Take a look at your what you do on a regular basis. What could get automated? If you find yourself having done something twice and there is chance you’ll have to do it again. Stop! Automate it.

Success requires that you be lazy

The old saying is that the best programmer is a lazy one. What that is really saying is the best programmers only do something once or twice and then automate it. I don’t claim to be the best coder or even a great one but one thing that helps me look good is automation.

Here is what I have automated in my world:

  • Running tests
  • Building application releases
  • Deploying software to QA
  • Deploying documentation for new releases to our website.
  • Deploying software ready for shipment

Things I would love to better automate in my world:

  • Updating a project’s libraries to the newest version.
  • Automating the setup of software downloads for our customers.
  • Pushing “What’s New” content into documentation for maintenance releases.
  • Integrating software downloads with our CRM so we know what version each customer has.

Part of my gig involves supporting a bunch of released software. Bugs happen. If I didn’t have it so that releasing patched software was push button I would go bah-zonkers.

What are you automating?

Tooling

Besides spreadsheets. There are boat loads of tools out there for automation. In my world I have used way too much NAnt and I am starting to use a ruby build tool called Rake. I’d love to hear about you have been successful with.

The Inauguration

Right now I am spelunking through blogger.com and having fun download templates and shuffling around widgets. This is fun. I love technology when it helps bring people together to share ideas. Oops I better write something of note before you, the reader, bail on me. I wrote some pithy stuff in this blog’s title about what The Glueist is about. I’ll quote it here partially to see what quoting something looks like with this blogger template and partially to archive it as I will surely change it and later down the road I’ll wish I had saved it.

The world needs people who know how to rummage through a world of potential and make something new.

This is where my head is right now. This is me. I am not the most creative person in the world but I keep my ears on the ground. Glueist?? you ask? and thanks for asking. I an not greatly enamored with adhesives or epoxies at large but with the idea of they way things fit together and how a squirt of mental glue and bring them together.

The new year is coming and this blog is a personal resolution of sorts to externalize the ramblings in my brain. I plan on talking a lot about technology and software development as that is where I thrive. Topics that are on the frothy top of my brain are automation. I’m sure to go in many other directions.

My time is up. I shall return.