Reputation: 345
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
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
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
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