Gavin Crawley
Gavin Crawley

Reputation: 345

Kicking off Windows Service at Set Time

I'm recently made the move from vb.net to C# and Im having problems kicking off a windows service that I have created. I want the service to run every day at a time being read from my app.config file. In vb.net I used a Timer and called a method:

Private WithEvents Alarm As Timer = New Timer(30000)
Public Sub OnTimedEvent(ByVal source As Object, ByVal e As ElapsedEventArgs) Handles Alarm.Elapsed

Heres the C# code I have so far:

namespace MyWindowsService
{
class Program : ServiceBase
{
  Timer alarm = new Timer(30000);
  public string str_dbserver;
  public string str_year;
  public string str_time;
  public string str_dbConnection;
  bool service_running;

static void Main(string[] args)
{
    ServiceBase.Run(new Program());
}

public Program()
{
  this.ServiceName = "MyWindowsService";
}


public void OnTimedEvent(object source, ElapsedEventArgs e)
{      
    service_running = false;

    //declare variables and get info from config file
    DateTime dtNow;
    dtNow = DateTime.Now;
    System.Configuration.AppSettingsReader configurationAppSettings = new System.Configuration.AppSettingsReader();
    str_dbserver = Convert.ToString(configurationAppSettings.GetValue("dbServer", typeof(System.String)));
    str_year = Convert.ToString(configurationAppSettings.GetValue("sYear", typeof(System.String)));
    str_time = Convert.ToString(configurationAppSettings.GetValue("stime", typeof(System.String)));

    //split time from config to get hour, minute, second
    string[] str_atime = str_time.Split(new string[] { ":" }, StringSplitOptions.None);

    //check that service is not currently running and time matches config file
    if (DateTime.Now.Hour == Convert.ToInt32(str_atime[0]) && DateTime.Now.Minute == Convert.ToInt32(str_atime[1]) && service_running == false)
    {
        //service now running so write to log and send email notification
        service_running = true;

        try
        {
            //call functions containing service code here
            Function1();
            Function2();
        }
        catch (Exception ex)
        {

        } //end try/catch

        //service now finished, sleep for 60 seconds
        service_running = false;
    } //end if 
} //end OnTimedEvent

I need my code to call the OnTimedEvent every 30 seconds to check the time from the config file and then run my code. Any help appreciated

Upvotes: 0

Views: 1204

Answers (3)

Gavin Crawley
Gavin Crawley

Reputation: 345

Thanks to 'Oded' and 'Martin James' for pointing me in the right direction. What I was missing in my solution was this. I had to add the following code to the contructor class so that it would recognize that the timer had elapsed:

//call onTimedEvent when timer reaches 60 seconds
alarm.Elapsed += new ElapsedEventHandler(OnTimedEvent);
// Set the Interval to 60 second.
alarm.Interval = 60000;

I then used the following to import the kernel32 dll:

using System.Runtime.InteropServices;

//import kernel32 so application can use sleep method
  [DllImport("kernel32.dll")]
  static extern void Sleep(uint dwMilliseconds);

By importing this dll i could then use Sleep(60000) once my code had finished executing. Thanks everyone for the help

Upvotes: 0

Martin James
Martin James

Reputation: 24847

Dump the timer, start a thread, use a Sleep(30000) loop.

Edit: Even better, get the RTC value and calculate how many ms remain until the next run time. Divide by 2 and Sleep() for that interval. Keep doing that until the interval is less than, say 100ms, then run the functions, Sleep() for another 1000, (to make sure that the RTC time-of-day now is later than the RTC time-of-day read from the config file), and loop round.

Upvotes: 1

spender
spender

Reputation: 120380

Why are you polling the time? Despite polling every 30s, under severe load/ThreadPool starvation, it's possible (though highly unlikely) that the timer won't fire in the minute slot required.

Why not figure out the TimeSpan until the due time and set the timer to fire at that time?

It's not clear which timer you're using, but I wouldn't use anything other than System.Threading.Timer for a Windows service.

Upvotes: 1

Related Questions