I create a windows service to run a piece of code and implemented timer in it to run it periodically.
My timer class is :
class TimerClass
{
private static System.Timers.Timer aTimer;
public static void Main()
{
aTimer = new System.Timers.Timer(1000);
aTimer.Elapsed += new ElapsedEventHandler(OnTimedEvent);
aTimer.Interval = 5000;
aTimer.Enabled = true;
GC.KeepAlive(aTimer);
}
private static void OnTimedEvent(object source, ElapsedEventArgs e)
{
aTimer.Stop();
DatabaseUpdation dbUp = new DatabaseUpdation();
File.AppendAllText(#"C:\Documents and Settings\New Folder\My Documents\demo\abc.txt", "Start" + " " + DateTime.Now.ToString() + Environment.NewLine);
dbUp.GetDatafromSource();
aTimer.Start();
}
}
And i am calling it from my Start method:
protected override void OnStart(string[] args)
{
TimerClass timer = new TimerClass();
}
But timer is not executing at all.
Can anyone find me the mistake here?
Thanks in advance
Please, read about Constructor
your initialization code should not be in public static void Main(), but instead in public TimerClass()
class TimerClass
{
private System.Timers.Timer aTimer;
public TimerClass()
{
aTimer = new System.Timers.Timer(1000);
aTimer.Elapsed += new ElapsedEventHandler(OnTimedEvent);
aTimer.Interval = 5000;
aTimer.Enabled = true;
GC.KeepAlive(aTimer);
}
private void OnTimedEvent(object source, ElapsedEventArgs e)
{
aTimer.Stop();
DatabaseUpdation dbUp = new DatabaseUpdation();
File.AppendAllText(#"C:\Documents and Settings\New Folder\My Documents\demo\abc.txt", "Start" + " " + DateTime.Now.ToString() + Environment.NewLine);
dbUp.GetDatafromSource();
aTimer.Start();
}
}
also your methods and aTimer should not be static.
You need to call Main method to start timer:
protected override void OnStart(string[] args)
{
TimerClass.Main();
}
BTW not very good name - I think something like Start will be better. Also I hope this is not your app entry point method.
You forgot to start your timer. Move it outside your elapse. Elapse is only called when your timer is expired.
aTimer.Start();
FYI you don't need to enable your timer once you call the start method
Try this:
class TimerClass
{
private static System.Timers.Timer aTimer;
public static void Main()
{
aTimer = new System.Timers.Timer(1000);
aTimer.Elapsed += new ElapsedEventHandler(OnTimedEvent);
aTimer.Interval = 5000;
GC.KeepAlive(aTimer);
}
public static void Start()
{
aTimer.Start();
}
private static void OnTimedEvent(object source, ElapsedEventArgs e)
{
aTimer.Stop();
DatabaseUpdation dbUp = new DatabaseUpdation();
File.AppendAllText(#"C:\Documents and Settings\New Folder\My Documents\demo\abc.txt", "Start" + " " + DateTime.Now.ToString() + Environment.NewLine);
dbUp.GetDatafromSource();
aTimer.Start();
}
}
and you need to call it like this:
protected override void OnStart(string[] args)
{
//TimerClass timer = new TimerClass();<==No need it's static class!!!
TimerClass.Main();
TimerClass.Start();
}
Related
I have a service that I want to run every X min using (for example) a timer.
This is not working, why? Any better way I can do this? Tried searching and didn't found anything that worked for me...The breakpoint never hits OnStop method...
static void Main()
{
WriteLine("service has started");
timer = new Timer();
timer.Enabled = true;
timer.Interval = 1000;
timer.AutoReset = true;
timer.Start();
timer.Elapsed += scheduleTimer_Elapsed;
}
private static void scheduleTimer_Elapsed(object sender, ElapsedEventArgs e)
{
WriteLine("service is runs again");
}
public static void WriteLine(string line)
{
Console.WriteLine(line);
}
I was in a bit same situation earlier. I used the following code, it worked for me.
// The main Program that invokes the service
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
static void Main()
{
ServiceBase[] ServicesToRun;
ServicesToRun = new ServiceBase[]
{
new Service1()
};
ServiceBase.Run(ServicesToRun);
}
}
//Now the actual service
public partial class Service1 : ServiceBase
{
public Service1()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
///Some stuff
RunProgram();
///////////// Timer initialization
var scheduleTimer = new System.Timers.Timer();
scheduleTimer.Enabled = true;
scheduleTimer.Interval = 1000;
scheduleTimer.AutoReset = true;
scheduleTimer.Start();
scheduleTimer.Elapsed += new ElapsedEventHandler(scheduleTimer_Elapsed);
}
protected override void OnStop()
{
}
void scheduleTimer_Elapsed(object sender, ElapsedEventArgs e)
{
RunProgram();
}
//This is where your actual code that has to be executed multiple times is placed
void RunProgram()
{
//Do some stuff
}
}
I'm updating my code to use Async, the issue is that to Timer.Elapsed requires a void return type, but this basically doesn't allow for an await, so the code doesn't wait and finishes too soon before everything is done.
Code:
public static void Main(string[] args)
{
Timer timer;
timer = new System.Timers.Timer();
timer.Interval = 3000;
timer.Elapsed += OnTimerAsync;
timer.Enabled = true;
timer.Start();
Console.WriteLine("Press the Enter key to exit the program... ");
Console.ReadLine();
Console.WriteLine("Terminating the application...");
}
public async static void OnTimerAsync(object sender, ElapsedEventArgs args)
{
await ExecuteWorkflowAsync();
}
private async static Task<bool> ExecuteWorkflowAsync()
{
List<Schedule> schedulesToRun;
try
{
await JobLoader.LoadAsync(schedulesToRun);
}
catch (Exception ex)
{
// Log ex
}
return true;
}
Is there a way to use the Timer object with Async?
Try this:
public async static void OnTimerAsync(object sender, ElapsedEventArgs args)
{
timer.Enabled = false;
await ExecuteWorkflowAsync();
timer.Enabled = true;
}
I have seen similar post of setting Timer at particular time ... I Dont want to run timer Whole Day ...I Want to start it at specific Time ..
Most of the suggestion is use Scheduled tasks ...but I want to do it with window service ....
Here is My Service Working Code :
public AutoSMSService2()
{
InitializeComponent();
if (!System.Diagnostics.EventLog.SourceExists("MySource"))
{
System.Diagnostics.EventLog.CreateEventSource(
"MySource", "MyNewLog");
}
eventLog1.Source = "MySource";
eventLog1.Log = "MyNewLog";
Timer checkForTime = new Timer(5000);
checkForTime.Elapsed += new ElapsedEventHandler(checkForTime_Elapsed);
checkForTime.Enabled = true;
}
protected override void OnStart(string[] args)
{
eventLog1.WriteEntry("In OnStart");
}
protected override void OnStop()
{
eventLog1.WriteEntry("In onStop.");
}
void checkForTime_Elapsed(object sender, ElapsedEventArgs e)
{
eventLog1.WriteEntry("Timer Entry");
}
My Timer is working fine and adding Log at 5 sec interval ..But I want to start Timer Lets Say 3:00 PM ...
private static void SetTimer(Timer timer, DateTime due)
{
var ts = due - DateTime.Now;
timer.Interval = ts.TotalMilliseconds;
timer.AutoReset = false;
timer.Start();
}
But I am not sure How to Implement it in Code ..
Any suggestion would be Helpful
If you want to do it every day, Hope this will help.
private System.Threading.Timer myTimer;
private void SetTimerValue ()
{
DateTime requiredTime = DateTime.Today.AddHours(15).AddMinutes(00);
if (DateTime.Now > requiredTime)
{
requiredTime = requiredTime.AddDays(1);
}
myTimer = new System.Threading.Timer(new TimerCallback(TimerAction));
myTimer.Change((int)(requiredTime - DateTime.Now).TotalMilliseconds, Timeout.Infinite);
}
private void TimerAction(object e)
{
//here you can start your timer!!
}
here an example with windows form but you can achieve the some thing with windows service
public partial class Form1 : Form
{
private bool _timerCorrectionDone = false;
private int _normalInterval = 5000;
public Form1()
{
InitializeComponent();
//here you calculate the second that should elapsed
var now = new TimeSpan(0,DateTime.Now.Minute, DateTime.Now.Second);
int corrTo5MinutesUpper = (now.Minutes/5)*5;
if (now.Minutes%5>0)
{
corrTo5MinutesUpper = corrTo5MinutesUpper + 5;
}
var upperBound = new TimeSpan(0,corrTo5MinutesUpper, 60-now.Seconds);
var correcFirstStart = (upperBound - now);
timer1.Interval = (int)correcFirstStart.TotalMilliseconds;
timer1.Start();
}
private void timer1_Tick(object sender, EventArgs e)
{
// just do a correction like this
if (!_timerCorrectionDone)
{
timer1.Interval = _normalInterval;
_timerCorrectionDone = true;
}
}
Please look at this piece of code
public partial class TestService : ServiceBase
{
private static System.Timers.Timer aTimer;
protected override void OnStart(string[] args)
{
aTimer = new Timer(10000 * 6 * 5); // 5 minutes interval
aTimer.Elapsed += new ElapsedEventHandler(OnTimedEvent);
aTimer.Enabled = true;
}
private void OnTimedEvent(object source, ElapsedEventArgs e)
{
......
}
}
When I start this service at say 4:00 pm, the first time OnTimedEvent is called is at 4:05 pm, then 4:10 pm and so on. I would like the OnTimedEvent to be called at 4:00 pm as soon as I start the service. Is there anything I am missing here?
Use a System.Threading.Timer rather than a System.Timers.Timer.
It has a constructor overload that in addition to specifying the interval allows you choose the start delay, which can be set to 0 to fire immediately.
For a Comparison of the timer classes, see Windows.Forms.Timer OR System.Threading.Timer (specifically 'Initial timer event schedulable?')
You could just call the event in the OnStart
OnTimedEvent(this, null)
System.Timers.Timer starts counting down from 5 minutes and then the event is triggered. So it won't be able to trigger and run the code till the timer reaches 0.
The code may be run before the event listener is enabled this way shown below:
public partial class TestService : ServiceBase
{
private static System.Timers.Timer aTimer;
protected override void OnStart(string[] args)
{
aTimer = new Timer(10000 * 6 * 5); // 5 minutes interval
aTimer.Elapsed += new ElapsedEventHandler(OnTimedEvent);
foo();
aTimer.Enabled = true;
}
private void OnTimedEvent(object source, ElapsedEventArgs e)
{
foo();
}
private void foo(){
.....
}
}
I am going nuts. I can't figure out the problem.
I have a windows service that has a simple timer method. If I start the service, it always gives out exception at onTimerElapsed event. But If I write my XMLOperation methods in a different method(but not timer which I only need) and call it from program.cs, it works just fine. The working code is at the bottom also.
partial class DatabaseService : ServiceBase
{
Timer timer = new Timer();
public DatabaseService()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
timer.Interval = 10000;
timer.Enabled = true;
timer.Elapsed += new ElapsedEventHandler(onElapsedTime);
timer.Start();
}
protected override void OnStop()
{
timer.Enabled = false;
}
public void onElapsedTime(object source, ElapsedEventArgs e)
{
try
{
XMLOperations operation = new XMLOperations();
operation.WebServiceFlexiCampaigns("http://www.flexi.com.tr/data/xml/pazaryeri/mobil.xml");
operation.WebServiceShopMilesCampaignsXMLRead("http://www.shopandmiles.com/xml/3_119_3.xml");
operation.WebServiceBonusCampaignsXMLRead("http://www.bonus.com.tr/apps/getcampaignxml.aspx?type=campaigns");
}
catch (Exception ex)
{
StreamWriter SW;
SW = File.CreateText("c:\\1.txt");
SW.WriteLine(ex.Message);
SW.Close();
}
}
here is the working one, but this time I could not manage to work that code in periods of time like I can do in timer event. I call test method manually from program.cs
partial class DatabaseService : ServiceBase
{
Timer timer = new Timer();
public DatabaseService()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
timer.Interval = 10000;
timer.Enabled = true;
timer.Elapsed += new ElapsedEventHandler(onElapsedTime);
timer.Start();
}
protected override void OnStop()
{
timer.Enabled = false;
}
public void test()
{
try
{
XMLOperations operation = new XMLOperations();
operation.WebServiceFlexiCampaigns("http://www.flexi.com.tr/data/xml/pazaryeri/mobil.xml");
operation.WebServiceShopMilesCampaignsXMLRead("http://www.shopandmiles.com/xml/3_119_3.xml");
operation.WebServiceBonusCampaignsXMLRead("http://www.bonus.com.tr/apps/getcampaignxml.aspx?type=campaigns");
}
catch (Exception ex)
{
StreamWriter SW;
SW = File.CreateText("c:\\1111.txt");
SW.WriteLine(ex.Message);
SW.Close();
}
}
You can try this thread (see SamAgain response):
http://social.msdn.microsoft.com/Forums/en/clr/thread/8fbca78b-5078-4a12-8abb-4051076febbb
Hope it will work.