Resetting Threading Timer if it's called a second time - c#

I'm trying to create a system where a trigger happens so doors open for 5 seconds, and then close again. I'm using Threading.Timer for this, using:
OpenDoor();
System.Threading.TimerCallback cb = new System.Threading.TimerCallback(OnTimedEvent);
_timer = new System.Threading.Timer(cb, null, 5000, 5000);
...
void OnTimedEvent(object obj)
{
_timer.Dispose();
log.DebugFormat("All doors are closed because of timer");
CloseDoors();
}
When I open a certain door, the Timer starts. After 5 seconds, everything closes again.
But when I open a certain door, wait 2 seconds, then open another door, everything closes after 3 seconds. How can I 'reset' the Timer?

Do not dispose the timer, just change it every time you open a door, e.g.
// Trigger again in 5 seconds. Pass -1 as second param to prevent periodic triggering.
_timer.Change(5000, -1);

You can do something like this:
// First off, initialize the timer
_timer = new System.Threading.Timer(OnTimedEvent, null,
Timeout.Infinite, Timeout.Infinite);
// Then, each time when door opens, start/reset it by changing its dueTime
_timer.Change(5000, Timeout.Infinite);
// And finally stop it in the event handler
void OnTimedEvent(object obj)
{
_timer.Change(Timeout.Infinite, Timeout.Infinite);
Console.WriteLine("All doors are closed because of timer");
}

Related

Execute a function ever 60 seconds

I want to execute a function every 60 seconds in C#. I could use the Timer class like so:
timer1 = new Timer();
timer1.Tick += new EventHandler(timer1_Tick);
timer1.Interval = 60 * 1000; // in miliseconds
timer1.Start();
Question is I have a long running process. Occasionally it make take several minutes. Is there a way to make the timer smart so if the function is already being executed then it should skip that cycle and come back 60 seconds later and if again it is in execution then again skip and come back 60 seconds later.
I would suggest you to have a class member variable bool variable with value false.
then in click event return if its true at the beginning.
and then set it to true, so that it will tell you that its currently in execution.
then write your logic.
and then once done finally set it to false again.
code will look like this.
private bool isRunning = false;
private void timer1_Tick(object sender, EventArgs e)
{
if (isRunning)
{
return;
}
isRunning = true;
try
{
... //Do whatever you want
}
finally
{
isRunning = false;
}
}
The modern and most clean way to do this is using Microsoft's new Period Timer:
var timer = new PeriodicTimer(TimeSpan.FromSeconds(n));
while (await timer.WaitForNextTickAsync())
{
//Business logic
}
If you need to abort such a ticker, you can pass a cancellation token to the WaitForNextTickAsync method.
Another advantage is this:
The PeriodicTimer behaves like an auto-reset event, in that multiple ticks are coalesced into a single tick if they occur between calls to WaitForNextTickAsync(CancellationToken). Similarly, a call to Dispose() will void any tick not yet consumed. WaitForNextTickAsync(CancellationToken) may only be used by one consumer at a time, and may be used concurrently with a single call to Dispose().
Source: https://learn.microsoft.com/en-us/dotnet/api/system.threading.periodictimer.waitfornexttickasync?source=recommendations&view=net-7.0#remarks
If you need more granularity (like "always at 10 am", use something like https://github.com/HangfireIO/Cronos
Use a timer, set it to 60 second
On Event:
try
Stop timer
Do logic
catch
What ever fail recovery
finally
Start the timer
Logic is run 60 seconds after last finish.
You can use a Stopwatch inside a loop: start the stopwatch, after 60 second call the function, reset the stopwatch, start the loop again.

Capture Countdown or Tick Event - Threading.Timer C#

I have developed a program using Threading.Timer to call a method after 30 seconds.
The method is getting called, it's working but I want to get the event so that I can know how many seconds are left out of 30 sec.
I need a kind of tick event which gets fired every seconds. So that I can show the remaining seconds as well. This is my code:
Timer timerObj;
timerObj = new Timer(UpdateUI, null, Timeout.Infinite, Timeout.Infinite);
timerObj.Change(30000, Timeout.Infinite);
public void UpdateUI(object state)
{
ShowQR= false;
}
How can I get countdown even ?
This is how you'd go about implementing Evk's suggestion:
Timer timerObj;
Stopwatch stopwatch;
...
timerObj = new Timer(UpdateUI, null, Timeout.Infinite, Timeout.Infinite);
timerObj.Change(1000, Timeout.Infinite);
stopwatch = Stopwatch.StartNew();
public void UpdateUI(object state)
{
if (stopwatch.Elapsed < TimeSpan.FromSeconds(30))
{
timerObj.Change(1000, Timeout.Infinite);
return;
}
stopwatch.Restart();
ShowQR= false;
}
Note how you start the Stopwatch at the same time as you call timerObj.Change() to start the timer running.
Also note how the timer is set to fire every second rather than every 30s.
Then in the timer handler, you simply check the elapsed time on the Stopwatch - if it's less that 30s then just return; otherwise, do the thing you want to do every 30s and (IMPORTANT!) restart the Stopwatch.

How to activate the timer?

I'm new in asp.net. Im develping a web-baised application that should prevent the user if he tried to login three times with wrong password.
I will disable the login button for 10 minutes then I will enable it.
this is the interface
and this is the timer code
protected void timer1_tick(object sender, EventArgs e)
{
timer--;
if (timer == 0)
{
Button1.Enabled = true;
Timer1.Enabled = false;
Label1.Visible = false;
}
}
but when I run the application, after 10 minutes it's refresh the page without enable the login button
If you are using a System.Tmers.Timer then simply call:
Timer1.Start();
If you are using a System.Threading.Timer then this should start immediately. The third argument in the constructor is the dueTime which is:
The amount of time to delay before callback is invoked, in milliseconds. Specify Timeout.Infinite to prevent the timer from starting. Specify zero (0) to start the timer immediately.
Source
So if this is non-zero your timer wont fire for the first time until after both the dueTime and period have elapsed. So if you have:
var timer1 = new Timer(callback, state, 10000, 10000);
the first time this will fire will be after 20 seconds and then it will fire every 10 seconds thereafter. If you want it to fire every 10 seconds then you need to specify 0 as the dueTime:
var timer1 = new Timer(callback, state, 0, 10000);

System.Threading.Timer in C# it seems to be not working. It runs very fast every 3 second

I've a timer object. I want it to be run every minute. Specifically, it should run a OnCallBack method and gets inactive while a OnCallBack method is running. Once a OnCallBack method finishes, it (a OnCallBack) restarts a timer.
Here is what I have right now:
private static Timer timer;
private static void Main()
{
timer = new Timer(_ => OnCallBack(), null, 0, 1000 * 10); //every 10 seconds
Console.ReadLine();
}
private static void OnCallBack()
{
timer.Change(Timeout.Infinite, Timeout.Infinite); //stops the timer
Thread.Sleep(3000); //doing some long operation
timer.Change(0, 1000 * 10); //restarts the timer
}
However, it seems to be not working. It runs very fast every 3 second. Even when if raise a period (1000*10). It seems like it turns a blind eye to 1000 * 10
What did I do wrong?
This is not the correct usage of the System.Threading.Timer. When you instantiate the Timer, you should almost always do the following:
_timer = new Timer( Callback, null, TIME_INTERVAL_IN_MILLISECONDS, Timeout.Infinite );
This will instruct the timer to tick only once when the interval has elapsed. Then in your Callback function you Change the timer once the work has completed, not before. Example:
private void Callback( Object state )
{
// Long running operation
_timer.Change( TIME_INTERVAL_IN_MILLISECONDS, Timeout.Infinite );
}
Thus there is no need for locking mechanisms because there is no concurrency. The timer will fire the next callback after the next interval has elapsed + the time of the long running operation.
If you need to run your timer at exactly N milliseconds, then I suggest you measure the time of the long running operation using Stopwatch and then call the Change method appropriately:
private void Callback( Object state )
{
Stopwatch watch = new Stopwatch();
watch.Start();
// Long running operation
_timer.Change( Math.Max( 0, TIME_INTERVAL_IN_MILLISECONDS - watch.ElapsedMilliseconds ), Timeout.Infinite );
}
I strongly encourage anyone doing .NET and is using the CLR who hasn't read Jeffrey Richter's book - CLR via C#, to read is as soon as possible. Timers and thread pools are explained in great details there.
It is not necessary to stop timer, see nice solution from this post:
"You could let the timer continue firing the callback method but wrap your non-reentrant code in a Monitor.TryEnter/Exit. No need to stop/restart the timer in that case; overlapping calls will not acquire the lock and return immediately."
private void CreatorLoop(object state)
{
if (Monitor.TryEnter(lockObject))
{
try
{
// Work here
}
finally
{
Monitor.Exit(lockObject);
}
}
}
Is using System.Threading.Timer mandatory?
If not, System.Timers.Timer has handy Start() and Stop() methods (and an AutoReset property you can set to false, so that the Stop() is not needed and you simply call Start() after executing).
I would just do:
private static Timer timer;
private static void Main()
{
timer = new Timer(_ => OnCallBack(), null, 1000 * 10,Timeout.Infinite); //in 10 seconds
Console.ReadLine();
}
private static void OnCallBack()
{
timer.Dispose();
Thread.Sleep(3000); //doing some long operation
timer = new Timer(_ => OnCallBack(), null, 1000 * 10,Timeout.Infinite); //in 10 seconds
}
And ignore the period parameter, since you're attempting to control the periodicy yourself.
Your original code is running as fast as possible, since you keep specifying 0 for the dueTime parameter. From Timer.Change:
If dueTime is zero (0), the callback method is invoked immediately.
var span = TimeSpan.FromMinutes(2);
var t = Task.Factory.StartNew(async delegate / () =>
{
this.SomeAsync();
await Task.Delay(span, source.Token);
}, source.Token, TaskCreationOptions.LongRunning, TaskScheduler.Default);
source.Cancel(true/or not);
// or use ThreadPool(whit defaul options thread) like this
Task.Start(()=>{...}), source.Token)
if u like use some loop thread inside ...
public async void RunForestRun(CancellationToken token)
{
var t = await Task.Factory.StartNew(async delegate
{
while (true)
{
await Task.Delay(TimeSpan.FromSeconds(1), token)
.ContinueWith(task => { Console.WriteLine("End delay"); });
this.PrintConsole(1);
}
}, token) // drop thread options to default values;
}
// And somewhere there
source.Cancel();
//or
token.ThrowIfCancellationRequested(); // try/ catch block requred.

How to reset a timer in C#?

There are three Timer classes that I am aware of, System.Threading.Timer, System.Timers.Timer, and System.Windows.Forms.Timer, but none of these have a .Reset() function which would reset the current elapsed time to 0.
Is there a BCL class that has this functionality? Is there a non-hack way of doing it? (I thought perhaps changing the time limit on it might reset it) Thought on how hard it would be to reimplement a Timer class that had this functionality, or how to do it reliably with one of the BCL classes?
I always do ...
myTimer.Stop();
myTimer.Start();
... is that a hack? :)
Per comment, on Threading.Timer, it's the Change method ...
dueTime Type: System.Int32 The
amount of time to delay before the
invoking the callback method specified
when the Timer was constructed, in
milliseconds. Specify
Timeout.Infinite to prevent the
timer from restarting. Specify zero
(0) to restart the timer immediately.
All the timers have the equivalent of Start() and Stop() methods, except System.Threading.Timer.
So an extension method such as...
public static void Reset(this Timer timer)
{
timer.Stop();
timer.Start();
}
...is one way to go about it.
For System.Timers.Timer, according to MSDN documentation, http://msdn.microsoft.com/en-us/library/system.timers.timer.enabled.aspx:
If the interval is set after the Timer has started, the count is
reset. For example, if you set the interval to 5 seconds and then set
the Enabled property to true, the count starts at the time Enabled is
set. If you reset the interval to 10 seconds when count is 3 seconds,
the Elapsed event is raised for the first time 13 seconds after
Enabled was set to true.
So,
const double TIMEOUT = 5000; // milliseconds
aTimer = new System.Timers.Timer(TIMEOUT);
aTimer.Start(); // timer start running
:
:
aTimer.Interval = TIMEOUT; // restart the timer
You could write an extension method called Reset(), which
calls Stop()-Start() for Timers.Timer and Forms.Timer
calls Change for Threading.Timer
I just assigned a new value to the timer:
mytimer.Change(10000, 0); // reset to 10 seconds
It works fine for me.
at the top of the code define the timer: System.Threading.Timer myTimer;
if (!active)
myTimer = new Timer(new TimerCallback(TimerProc));
myTimer.Change(10000, 0);
active = true;
private void TimerProc(object state)
{
// The state object is the Timer object.
var t = (Timer)state;
t.Dispose();
Console.WriteLine("The timer callback executes.");
active = false;
// Action to do when timer is back to zero
}
For a Timer (System.Windows.Forms.Timer).
The .Stop, then .Start methods worked as a reset.
You can do timer.Interval = timer.Interval
I do the following.
Disposing the timer and initializing it again.
But this will erase any event you attached to this timer.
timer.Dispose();
timer = new System.Timers.Timer();
Other alternative way to reset the windows.timer is using the counter, as follows:
int timerCtr = 0;
Timer mTimer;
private void ResetTimer() => timerCtr = 0;
private void mTimer_Tick()
{
timerCtr++;
// Perform task
}
So if you intend to repeat every 1 second, you can set the timer interval at 100ms, and test the counter to 10 cycles.
This is suitable if the timer should wait for some processes those may be ended at the different time span.
i do this
//Restart the timer
queueTimer.Enabled = true;

Categories

Resources