views:

64

answers:

3

Hi all,

I'm running a C# program (console application, soon to be converted to a Windows Service) where I need to be able to email administrators about errors in the service, but I need it to not send our an email for every error if the number of errors in the last few minutes exceeds 4-5, so it'll only send one email saying there are multiple errors.

I understand I'd use a timer in someform, but can anyone offer any more specific advice? I'd be very grateful

A: 

If you track each email you send using a database, you can always poll the database to see how many emails you have seen for a given error over a given period of time etc. In the few projects I've worked on where emailing was a requirement, logging of sent emails has always been a sister requirement, thus creating a solution to your problem.

DJ Quimby
You could use an embedded database such as SQLite (http://sqlite.phxsoftware.com/)
Tony
A: 

Use save the errors in a list then use System.Threading.Timer.

Pass a delegate that wraps up a SendEmail method.

Noel Abrahams
A: 

Modified from MSDN. Note comments about declaration and cleanup of Timer object aTimer.

using System;
using System.Timers;
using System.Threading;

public class Timer2
{
    private static System.Timers.Timer aTimer;
    private static List<string> errors = new List<string>();
    private static readonly int interval = 300000;  // 5 minutes at present
    private static readonly int trigger = 10;       // send msg if > 10 errors

    // Message processing - error detection
    public static void processMessage(Message message)
    {
      // do the work here
      // then check error
      if (message.HasError)
      {
        // add error to pending list
        lock (errors)
        {
          string newErrorData = "got another one!";
          errors.Add(newErrorData);
          ++trigger;
        }
      }
    }

    public static void Main()
    {
        // Normally, the timer is declared at the class level,
        // so that it stays in scope as long as it is needed.
        // If the timer is declared in a long-running method,  
        // KeepAlive must be used to prevent the JIT compiler 
        // from allowing aggressive garbage collection to occur 
        // before the method ends. (See end of method.)
        //System.Timers.Timer aTimer;

        // Create a timer with specified interval.
        aTimer = new System.Timers.Timer(interval);

        // Hook up the event handler for the Elapsed event.
        aTimer.Elapsed += new ElapsedEventHandler(OnTimedEvent);
        aTimer.Enabled = true;

        // Kick off message handling - don't forget to clean up the timer when 
        // you wish to exit
        while (moreMessages)
        {
           Message message = getNextmessage();
           ProcessMessage(message);
        }
        // cleanup here when messages are drained
        // If the timer is declared in a long-running method, use
        // KeepAlive to prevent garbage collection from occurring
        // before the method ends.
        //GC.KeepAlive(aTimer);        }

    private static void OnTimedEvent(object source, ElapsedEventArgs e) 
    {
        object errorEmail = null;
        lock (errors)
        {
            if (errors.Count > trigger)
            {
               // init message to contain errors here
               errorEmail = new ErrorEmail();
               foreach (string err in errors)
               {
                  // add error info to message
               } 
               errors.Clear();
               trigger = 0;
            }
        }
        if (errorEmail != null)
        {
          // send message outside the lock
          Send(errorEmail);
        }
    }
}
Steve Townsend