How to start method on timer from windows service? - c#

I have a method that executes in about 10 minutes. And it goes well just by itself. I need to start this method every hour using windows service (this is obligatory). So I've written my service by some examples (just one invoke for start):
partial class ServiceWSDRun : ServiceBase
{
protected override void OnStart(string[] args)
{
Thread t = new Thread(WebServiceDownload.MainProgram.Execute);
t.Start();
}
}
Now when I install it, it launches my method in a new thread but this thread seem to end with the OnStart() - it actually logs some info from the beginning of me method. Why does it stop and what should I do?
And I'm thinking in the end I should have something like this:
partial class ServiceWSDRun : ServiceBase
{
System.Timers.Timer timer = null;
protected override void OnStart(string[] args)
{
Thread t = new Thread(WebServiceDownload.MainProgram.Execute);
t.Start();
timer = new System.Timers.Timer();
timer.Interval = 60 * 60 * 1000; // 1 hour
timer.Elapsed += new System.Timers.ElapsedEventHandler(OnTimer);
timer.Enabled = true;
}
public void OnTimer(object sender, System.Timers.ElapsedEventArgs args)
{
WebServiceDownload.MainProgram.Execute();
}
protected override void OnStop()
{
timer.Enabled = false;
}
}
How do I make it work? And keep in mind that method takes ~10 mins to execute.

You should use System.Threading.Timer instead of System.Timers.Timer.
Here is the reference for this:
https://msdn.microsoft.com/en-us/library/system.threading.timer(v=vs.110).aspx
Also, another thread about the same topic:
System.Timers.Timer vs System.Threading.Timer
You should lock the execution, avoiding the second execution before the first one finishes.

Related

Running timer immediately in a windows service

I have created a windows service on VS.net C#
In the OnStart event I start a timer.
In side the timer I call a function called DO()
the process of the DO() function is very long ( takes more than hour)
The process suppose to go this way
Start Then call the time immediately but due to the timer interval need to wait another day
protected override void OnStart(string[] args)
{
eventLog1.WriteEntry("In OnStart.");
try
{
Timer timer = new Timer();
timer.Interval = 1000 * 60 *60 * 24;
timer.Elapsed += new ElapsedEventHandler(this.OnTimer);
timer.Start();
DO();
}
catch (Exception ex)
{
eventLog1.WriteEntry("ERROR (OnStart) : " + ex.ToString());
}
}
public void OnTimer(object sender, ElapsedEventArgs args)
{
DO();
}
private void DO()
{
// Some process takes an hour
}
When the service starts it stays an hour in "Starting"
Is there a way I can start my service DO() function immediatly once the service started but not from the OnStart event?
Presuming you left nothing out of your example, your timer elapsed method will run on the ThreadPool.
So I would change this line in OnStart
DO();
...with this line:
ThreadPool.QueueUserWorkItem(x => Do());
It has the same net effect of what would happen if the timer fired immediately and, more importantly, will not block on that line.

System.timer doesnt throw events and console terminates immediatly

I need a timer that executes every minute but i have trouble getting the timer to run at all with code that i used before. so i guess i am doing sth fundamentally wrong that is not code related but even in a just newly created Console project in visual studio community 2017 it doesn't execute the _timer_elapsed method. the console terminates immediately without errors as if it has executed every code
using System;
using System.Timers;
namespace Test
{
class Program
{
static Timer _timer;
public static void Main(string[] args)
{
var timer = new Timer(60000);
timer.Elapsed += new ElapsedEventHandler(_timer_Elapsed);
timer.Enabled = true;
_timer = timer;
}
static void _timer_Elapsed(object sender, ElapsedEventArgs e)
{
Console.WriteLine("test");
}
}
}
what am I missing here?
You need your program to stay alive, rather than return from Main. An quick and easy way to do this is to wait for some input at the end:
public static void Main(string[] args)
{
var timer = new Timer(60000);
timer.Elapsed += new ElapsedEventHandler(_timer_Elapsed);
timer.Enabled = true;
_timer = timer;
Console.ReadLine();
}
There is no such thing as a bad question.
(Though some questions show more affinity with programming, and some show less.)
If you look at your code, your main sets up a timer and then proceeds to terminate. So, of course your program exits immediately and the timer is never fired.
In order to see your timer firing, your program will need to keep running for at least as long as one period of your timer.

Determine if Timer is running

In this Link it shows how to determine if a timer is running. For me it is not working.
I have the timer declared in a static class as shown
public static class ServiceGlobals // Globals
{
public static System.Timers.Timer _timer = new System.Timers.Timer();
}
}
On Start-up of my service, I set the timer properties
protected override void OnStart(string[] args)
{
ServiceGlobals._timer.AutoReset = false;
ServiceGlobals._timer.Interval = (3000);
ServiceGlobals._timer.Elapsed += new System.Timers.ElapsedEventHandler(_timer_Elapsed);
ServiceGlobals._timer.Enabled = true;
ServiceGlobals._timer.Start(); // Start timer
}
then i check if it is running in one of my methods but even when it is running the code is always false
if (ServiceGlobals._timer.Enabled) // Check if the timer is running
{
// Return error.........
}
You must have missed this part of the thread you linked:
"If Timer.AutoReset is true, then Enabled will automatically be set to false the first time the timer expires."

Can my use of System.Threading.Timer be more efficient

I´m looking for some advice about making my code more efficient. What I would like to do is to have a System.Threading.Timer that runs some job every hour or so, the job is not going to be very heavy but I would like to have a code that does not take much of resources. I plan to run this code in a windows service.
This is what I have so far.
class Program
{
private static Timer timer;
static void Main(string[] args)
{
SetTimer();
}
static void SetTimer()
{
timer = new Timer(Write);
var next = DateTime.Now.AddHours(1);
var nextSync = (int)(next - DateTime.Now).TotalMilliseconds;
timer.Change(nextSync, Timeout.Infinite);
}
static void Write(object data)
{
Console.WriteLine("foo");
SetTimer(); //Call the SetTimer again for the next run.
}
}
What do you guys think? Can I make my code more efficient?
All advice is much appreciated!
Several points:
You do not have to create a new timer every hour.
Setting the second parameter to infinite, makes you have to reload the timer manually. But... In this case, why should you?
You make a difficult calculation to create a timespan from one hours form now: now + 1 hour - now. This can solved easily.
Try this:
class Program
{
private static Timer timer = new Timer(Write, null, TimeSpan.FromHours(1), TimeSpan.FromHours(1));
static void Main(string[] args)
{
}
static void Write(object data)
{
Console.WriteLine("foo");
}
}
This is not good, since you create and abandon a brand new timer each iteration. Move
timer = new Timer(Write);
into Main so that it only executes once, then SetTimer can reuse this single Timer object.
In WPF:
DispatcherTimer timer = new DispatcherTimer();
timer.Tick += timer_Tick;
timer.Interval = = new TimeSpan(1, 0, 0); //once an hour
timer.Start();
void timer_Tick(object sender, EventArgs e)
{
//do your updates
}

timer inside thread

My Aim: I am having a credit card wait window. I will call a function from the client to wait for the credit card swipe. In order to avoid the program getting stuck while waiting for the credit card . I am using a delegate to run a timer. The delegate will call a timer. The timer periodically checks for the presence for the card. If it found a card it will a callback/delegate assigned by the client.
the code is given below, my questions are
1) Will the _timer_Elapsed will get called within the thread so that it will add minimum overhead to the ui window?
2) How can i call the callback/event of the base class from the timer function. I have written a protected method which will call the event/delegate in the base class. I need to call the protected method from the timer function( which is inside a delegate in the derived class.)?
Wait wait = delegate()
{
_timer = new Timer(3000); // Set up the timer for 3 seconds
_timer.Elapsed += new ElapsedEventHandler(_timer_Elapsed);
_timer.Enabled = true; // Enable it
static void _timer_Elapsed(object sender, ElapsedEventArgs e)
{
// if(CheckCardsPresence())
{
//RaiseEvent()
//KillTimer()
}
//else
{
// do nothing. wait more
}
}
};
wait.Invoke();
No, the timer callback will not execute on the delegate-thread.
How could it? A timer cannot 'break in' on a thread, that thread has to poll.
This delegate-thread will terminate immediately after starting the timer. Which means you don't need this thread at all. Unless there is code not shown.
When you use a System.Threading.Timer the callback will be pushed onto the Threadpool.
To the second question (do try to ask only 1 question at a time)
A protected member should be accessible from an anonymous (embedded) method. Do you have a concrete problem?
From the MSDN documentation (sorry I got the wrong class the first time around)
This Windows timer is designed for a single-threaded environment where UI threads are used to perform processing. It requires that the user code have a UI message pump available.
This is a roundabout way of saying that the event will be raised on the UI thread / message pump, i.e. the answer to your first question is yes as long as by "the thread" you mean "the UI thread".
I don't really understand your second question - what base class are you talking about?
First, that code will not compile. You cannot declare a named method from within another method. You can, however, declare an anonymous method or lambda expression and then assign it to a delegate reference.
There may not be any need to do asynchronous polling of the credit card device. You might be able to use a System.Windows.Forms.Timer and perform the polling from the Tick event which runs on the UI thread. This would be acceptable if the CheckCardsPresence is a quick operation.
public class CreditCardWaitWindow : Form
{
private System.Windows.Timer timer = new System.Windows.Timer();
private void Form_Load(object sender, EventArgs args)
{
timer.Tick += OnTick;
timer.Interval = 3000;
timer.Start();
}
private void OnTick(object sender, EventArgs args)
{
if (CheckCardsPresence())
{
RaiseEvent();
timer.Stop();
}
}
}
If polling the credit card device is a time consuming operation then you will want to perform this operation on another thread to avoid blocking the UI.
public class CreditCardWaitWindow : Form
{
private System.Timers.Timer timer = new System.Timers.Timer();
private void Form_Load(object sender, EventArgs args)
{
timer.Elapsed += OnElapsed;
timer.Interval = 3000;
timer.AutoReset = false;
timer.Start();
}
private void OnElapsed(object sender, ElapsedEventArgs args)
{
if (CheckCardsPresence())
{
Invoke(
(MethodInvoker)(() =>
{
RaiseEvent();
}), null);
}
else
{
timer.Start();
}
}
}
Here is a cleaner implementation using a Task.
public class CreditCardWaitWindow : Form
{
private void Form_Load(object sender, EventArgs args)
{
Task.Factory.StartNew(
() =>
{
while (true)
{
Thread.Sleep(3000);
if (CheckCardsPresence()) break;
}
}, TaskCreationOptions.LongRunning).ContinueWith(
() =>
{
RaiseEvent();
}, TaskScheduler.FromCurrentSychronizationContext());
}
}
And to really top things off you could do this in C# 5.01 with the new await keyword. I am not sure it can get anymore succinct than that!
public class CreditCardWaitWindow : Form
{
private async void Form_Load(object sender, EventArgs args)
{
while (!CheckCardsPresence()) await Task.Delay(3000);
RaiseEvent();
}
}
1C# 5.0 has not been released yet.

Categories