C# Pause Program Execution - c#

I am writing a program that will perform an operation every 10 or 15 minutes. I want it to be running all the time, so I need something that is cheap on processing power. What I have read so far seems to suggest that I want to use a Timer. Here is a clip of the code I have so far.
class Program {
private static Timer timer = new Timer();
static void Main(string[] args) {
timer.Elapsed += new ElapsedEventHandler(DoSomething);
while(true) {
timer.Interval = TimerMilliseconds(); // The duration of the wait will differ each time
timer.Enabled=true;
}
}
}
The problem here is that the while loop just keeps executing rapidly. How do I halt execution until the timer is elapsed. My program really doesn't need to be multi threaded. Is a Timer the right tool for this job?
Thank you in advance for any help!
UPDATE: Sorry for the confusion. I have implemented the DoSomething method. I just did not include it as I don't believe it is part of my issue.

Timer's will fire off the Elapsed event once the specified interval has elapsed.
I would do something like this:
private static Timer timer = new Timer();
static void Main(string[] args)
{
timer.Elapsed += new ElapsedEventHandler(DoSomething);
timer.Interval = TimerMilliseconds(); // The duration of the wait will differ each time
timer.Enabled=true;
Console.ReadKey(); //Wait for keypress to terminate
}
You could also implement this as a service so you don't have to have a blocking call like Console.ReadKey to keep the program from terminating.
Finally, you could just change the interval in the event handler:
static void DoSomething(...)
{
timer.Stop();
timer.Interval = TimerMilliseconds();
...
timer.Start();
}

The problem with this code is that you're using a loop to set the Interval and Enabled properties of the Timer, which will execute said assignments over and over - it's not waiting for the timer to execute in some way.
If your application doesn't need to be mutlithreaded, then you might be better simply calling Thread.Sleep between executions.
class Program {
static void Main(string[] args) {
while(true) {
Thread.sleep(TimerMilliseconds()); // The duration of the wait will differ each time
DoSomething();
}
}
}

take out the timer and loop from your logic. Just use windows scheduler to execute your program after 15 minutes. Or you can use windows services. Please read Best Timer for using in a Windows service

remove the while loop completely.
inside of the DoSomething() function (once implemented) stop timer at start and at the end reset the interval before restarting the timer.

I guess the comments and answrs already provide the hints you need, but the MSDN docs for Timer actually provide a nice example. In my opinion the Timer approach is a bit tidier, it's easier to read your intentions and abstracts away the details of invoking your scheduled code.

Here's another alternative approach using ManualResetEvent and WaitOne(). This will allow you to halt the main thread without worrying about it being killed accidentally by an errant keypress. You can also Set() the MRE when certain conditions are met to allow the app to exit gracefully:
class Program
{
private static Timer timer;
private static ManualResetEvent mre = new ManualResetEvent(false);
static void Main(string[] args)
{
timer = new Timer(TimerCallback, null, 0, (int)TimeSpan.FromMinutes(15).TotalMilliseconds);
mre.WaitOne();
}
private static void TimerCallback(object state)
{
// ... do something in here ...
Console.WriteLine("Something done at " + DateTime.Now.ToString());
}
}

Related

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.

Prevent my console application from closing after a .Net.Timer starts

So I have this simple code:
static void Main(string[] args)
{
var timer = new Timer(0.5 * 60 * 1000); // 0.5 minutes times 60 seconds times 1000 miliseconds
timer.Elapsed += new System.Timers.ElapsedEventHandler(Start);
timer.AutoReset = true;
timer.Start();
}
Which starts a timer that starts the whole program logic. Problem is, the console application closes and nothing is done. How do I prevent this? I know that if I do something like while(true) it works, but that does not seem like an elegant/proper solution.
Maybe try
Console.Read();
At the end of the code
Thanks to this your console window will not be closed as long as a user will not press a key.
The last answer is 7 years old. In the meantime, methods from System.Threading like Timer, Sleep, ...
should not be used anymore. They carry the risk of deadlocks, and I have to warn against their use especially in ASP.NET Core.
There are several things to consider:
No program runs forever. What happens when the program should be closed (by a shutdown or a signal)?
The termination must be implemented in your program logic. Many async .NET Core methods supports a CancellationToken as a parameter.
There are 2 approaches to create an "endless" program:
Worker Services in .NET Core are the common approach today to write programs that should run permanently as a service. They can be registered as Windows Service.
More Infos on learn.microsoft.com and devblogs.microsoft.com if you want to register your service as a "real" service.
If you need a "real" console application that performs tasks in the foreground, this can be done with the following sample code:
using System;
using System.Threading.Tasks;
using System.Threading;
namespace DemoApp
{
internal class Program
{
private static int _isRunning = 0;
private static async Task Main(string[] args)
{
// No program can run infinitely. We always have to provide a mechanism for termination.
var tcs = new CancellationTokenSource();
var periodTimeSpan = TimeSpan.FromSeconds(10);
// This mechanism is CTRL+C, so we catch this.
Console.CancelKeyPress += (sender, e) =>
{
tcs.Cancel();
e.Cancel = true;
};
try
{
// No endless loop. We are checking for a cancellation request!
while (!tcs.IsCancellationRequested)
{
// Perform your work.
var task1 = Run(tcs.Token);
var task2 = Task.Delay(periodTimeSpan, tcs.Token);
// If the execution time of Run is greater than periodTimeSpan, we will wait. Depends on your needs.
await Task.WhenAll(task1, task2);
}
}
catch (TaskCanceledException)
{
Console.WriteLine("User canceled your app.");
}
}
private static async Task Run(CancellationToken token)
{
// Should never occur if you use WhenAll()
if (Interlocked.Exchange(ref _isRunning, 1) == 0)
{
// Perform your work.
_isRunning = 0;
}
}
}
}
Add a Console.ReadKey(); this will allow you to close the console window by pressing any key.
static void Main(string[] args)
{
var timer = new Timer(0.5 * 60 * 1000); // 0.5 minutes times 60 seconds times 1000 miliseconds
timer.Elapsed += new System.Timers.ElapsedEventHandler(Start);
timer.AutoReset = true;
timer.Start();
Console.ReadKey();
}
If you want to just run a timer and wait, then Console.Read() is your friend.
The reason why your code is terminating is because the function initializes the timer, starts it and then ... hits the end of the Main function. As a result, the function exits.
The current code doesn't do anything useful (besides starting a timer which is ignored).
If you want to see your timer in action, do some other work after you start the timer. Then, stop the timer after an interval and print it/evaluate it how you deem fit. (The timer doesn't run on the main thread, whereas something like Console.Read() will be on the main thread and thus, block the thread until you have input)
Your console application does not end because the timer starts. It ends because the program reaches the end of the Main() method.
Whatever action you take to prevent the program from exiting Main() will help. While many proposed solutions actually do this. I wanted to highlight the fact that it's not the timer causing the issue.

Alternative to Thread.Sleep

Working on a windows service, which has to process request in every predefined interval of time. Thread.Sleep does the work perfectly fine but problem with this is when service is invoked to be stopped, service freeze if thread is in sleep mode.
I have read about the alternative approach like Timer, but problem with that is after that defined interval new thread is getting started.
Is there a better way to achieve same result and not run in to issue.
What you're looking for is the ability to respond to the notification of two different events - (1) when the timer elapses and (2) when the service is stopped. #Anurag Ranhjan is on the right track with WaitHandle, but you have two events, not one. To properly handle this, do the following.
First, define the two events you care about using ManualResetEvent. You can use AutoResetEvent if you prefer; I just prefer resetting the events manually.
using System.Threading;
ManualResetEvent shutdownEvent = new ManualResetEvent();
ManualResetEvent elapsedEvent = new ManualResetEvent();
You need to trigger these events when they occur. For the shutdownEvent, it's easy. In the OnStop callback of your Windows service, just set the event.
protected override void OnStop
{
shutdownEvent.Set();
}
For the elapsedEvent, you could do this a couple different ways. You could create a background thread, i.e., the ThreadPool, that uses Thread.Sleep. When the thread wakes up, set the elapsedEvent and go back to sleep. Since it's a background thread, it won't hang your service when it shuts down. The alternative, as you've already suggested, is to use a timer. This is how I do it.
using System.Timers;
Timer timer = new Timer();
timer.Interval = 5000; // in milliseconds
timer.Elapsed += delegate { elapsedEvent.Set(); };
timer.AutoReset = false; // again, I prefer manual control
timer.Start();
Now that you've got events being set properly, put them in a WaitHandle array.
WaitHandle[] handles = new WaitHandle[]
{
shutdownEvent,
elapsedEvent
};
Instead of the WaitHandle.WaitOne method, use the WaitHandle.WaitAny method inside a while loop, like this.
while (!shutdownEvent.WaitOne())
{
switch (WaitHandle.WaitAny(handles))
{
case 0: // The shutdownEvent was triggered!
break;
case 1: // The elapsedEvent was triggered!
Process(); // do your processing here
elapsedEvent.Reset(); // reset the event manually
timer.Start(); // restart the timer manually
break;
default:
throw new Exception("unexpected switch case");
}
}
I've condensed this example from production code in my project. I know this mechanism works, but I may have missed something in the writeup. Let me know if you have any questions.
You can use WaitHandle.WaitOne instead. You can wait for closing event to trigger or timeout that you are specifying in predefined interval of time.
static AutoResetEvent seviceStopRequested = new AutoResetEvent(false);
....
((AutoResetEvent)stateInfo).WaitOne([timeout], false)
Then when Service stop is invoked, you can just trigger the event
seviceStopRequested .Set();
I usually use the following pattern:
public class MyJob
{
System.Threading.Timer _timer;
bool _isStopped;
public void MyJob()
{
_timer = new Timer(OnWork, null, TimeSpan.FromSeconds(30), TimeSpan.FromSeconds(-1));
}
private void OnWork(object state)
{
//[.. do the actual work here ..]
if (!_isStopped)
_timer.Change(TimeSpan.FromSeconds(30), TimeSpan.FromSeconds(-1));
}
public void Stop()
{
_isStopped = true;
_timer.Change(TimeSpan.FromSeconds(-1), TimeSpan.FromSeconds(-1));
}
public void Start()
{
_isStopped = false;
_timer.Change(TimeSpan.FromSeconds(30), TimeSpan.FromSeconds(-1));
}
}
Key points:
Only using the initial interval gives you full control of when the timer is started again (i.e. the work time is not counted in the timer interval)
Changing the timer to -1 seconds pauses it until changed again
It should therefore work with all your requirements.
Use a Timer to add commands/tasks including the task for shutdown to a blocking queue. Make your service thread to wait for tasks on the blocking queue and execute them when available. The timer thread will keep adding the tasks to the queue periodically.
For what it is worth most of the blocking calls in the .NET BCL will respond to Thread.Interrupt. That is, they will not wait for the full amount of time specified when called and instead return immediately. However, I would avoid using this method and instead use a single ManualResetEvent to perform both the idle waiting and the shutdown signal. It would look like this.
public class MyServer : ServiceBase
{
private ManualResetEvent shutdown = new ManualResetEvent(false);
protected override void OnStart(string[] args)
{
new Thread(
() =>
{
while (!shutdown.WaitOne(YourInterval))
{
// Do work here.
}
}).Start();
}
protected override void OnStop()
{
shutdown.Set();
}
}

C# Timer vs Thread in Service

I have a Service that hits a database every 10 sec and gets the data if there is any. The thing is that processing this data can take up to 30 sec. If I use a Timer with 10 sec interval the service will get the same data twice.
The effect i´m trying to achieve(Just for visualization):
while(true)
{
if(Getnrofrows() > 0)
do stuff
else
sleep for 10 sec
}
Ppl saying Thread.Sleep is a bad idea in production services, how do I do this with timers?
/mike
Did you try to set Timer property auto reset to false, and enabling timer again when process of refreshing data is over
using System;
public class PortChat
{
public static System.Timers.Timer _timer;
public static void Main()
{
_timer = new System.Timers.Timer();
_timer.AutoReset = false;
_timer.Interval = 100;
_timer.Elapsed += new System.Timers.ElapsedEventHandler(_timer_Elapsed);
_timer.Enabled = true;
Console.ReadKey();
}
static void _timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
//Do database refresh
_timer.Enabled = true;
}
}
I don't see any problems with using Sleep at all other than you might end up with ugly code.
To answer your question:
public class MyTest
{
System.Threading.Timer _timer;
public MyTest()
{
_timer = new Timer(WorkMethod, 15000, 15000);
}
public void WorkMethod()
{
_timer.Change(Timeout.Infinite, Timeout.Infinite); // suspend timer
// do work
_timer.Change(15000, 15000); //resume
}
}
There is nothing wrong with this approach. A sleeping thread does not consume any CPU cycles.
If you need to do something exactly every X seconds, a timer is the way to go. If, on the other hand, you want to pause for X seconds, then Thread.Sleep is appropriate.
Thread.Sleep is not bad in itself in a service, just that you need to be responsive to service commands, so your worker thread should not go to sleep for an hour, but rather needs to sleep for short periods of time and then wake up and listen if the service controller part of the service is telling it to stop for some reason.
You want to make it so that if the admin tells your service to stop, it'll stop quickly enough so that it won't get any timeout messages where the admin can't be sure that your service is stopped and it's safe to reboot the machine or similar.

Quick C# threading class

Got a quick question on creating a C# thread.
It needs to run every 10 minutes
The worker will do work then go into sleep for another 10 minutes
It can also be triggered to run immediately by calling Trigger()
It can be stopped by calling Stop()
I've created one with ManualResetEvent, which is set when Stop() is called. This works well but do I need to create another ManualResetEvent or wait handle in order to be able to trigger the worker immediately?
If by Stop you mean Stop waiting and don't run again then I think a Threading.Timer will be a good (lean) choice.
You can activate a timer with a DoWork() method and a 10 minutes interval. It will use the ThreadPool which seems the best choice here. Trigger() can queue DoWork directly on the Pool and Stop() can deactivate the Timer. DoWork() shouldn't use Sleep() and be suitable for the ThreadPool.
Using a timer here makes sense. Here's a quick code-snippet which I haven't tested.
private System.Timers.Timer _timer = null;
public void Constructor()
{
_timer = new System.Timers.Timer(600000);
_timer.Elapsed += new ElapsedEventHandler(t_Elapsed);
}
public void ForceDoWork()
{
//unsubscribe to timer event, so work dowsnt get fired twice
_timer.Elapsed -= new ElapsedEventHandler(t_Elapsed);
StartWorking();
_timer.Elapsed += new ElapsedEventHandler(t_Elapsed);
}
public void StartWorking()
{
ThreadPool.QueueUserWorkItem(new WaitCallback(WorkToBeDone));
}
private void WorkToBeDone(object state)
{
//work here
}
public void t_Elapsed(object sender, ElapsedEventArgs e)
{
StartWorking();
}
Yes, you'll need another wait handle to force thread to execute. You'll basically have to WaitOne for this handle for 10 minutes, thus either elapsing a timeout or continuing whenever the wait handle becomes signalled.
Don't forget to switch that handle to a non-signalled state, though.

Categories