Timer event handler keeps getting called? - c#

I seem to have a thread issue I think, I have written a timer to return to the main screen if its on any other screen for 5 seconds. This code works fine the first time the ResetScreen() is called, but after it returns to the main screen itself, I can't navigate to any other screen as it keeps returning to the Timer event handler.
I also tested this without the this.Dispatcher.Invoke and replaced it with a message box, and it just constant pops up about every second.
private void ResetScreen()
{
if (!mainScreen)
{
myTimer = new System.Timers.Timer();
myTimer.Elapsed += new ElapsedEventHandler(OnTimedEvent);
myTimer.Interval = 5000;
myTimer.Start();
}
}
private void OnTimedEvent(object source, ElapsedEventArgs e)
{
myTimer.Stop();
this.Dispatcher.Invoke((Action)(() =>
{
// show main screen
}));
}
Edit:
I think its just a timer issue in general. Just can't seem to stop the timer.

When using System.Timers.Timer() you need to explicitly set the AutoReset property to false:
myTimer = new System.Timers.Timer();
myTimer.Elapsed += new ElapsedEventHandler(OnTimedEvent);
myTimer.Interval = 5000;
myTimer.AutoReset = false;
myTimer.Start();
Check out the documentation and examples on MSDN.

Related

How to repeat it at every X intervals?

on Get Property i am checking for DNS LookUp
But it is only executed at startup only..How to execute it at every X intervals
System.Net.IPHostEntry ipHe = System.Net.Dns.GetHostByName("www.google.com");
return (#"Images/online.png");
I'm making a lot of assumptions here, but I assume you are talking about keeping a WPF form updated with an "online" status that has an auto-refresh feature? And doing so in the MVVM model.
If those assumptions are right, in your view model you can use a System.Timers.Timer that will fire at any Interval you specify, and it can execute any method you specify by hooking into its Elapsed event.
public class ViewModel{
private static System.Timers.Timer aTimer;
public ViewModel()
{
aTimer = new Timer();
aTimer.Interval = 2000; // every two seconds
// Hookup to the elapsed event
aTimer.Elapsed += DoWork;
// Have the timer fire repeated events (true is the default)
aTimer.AutoReset = true;
// Start the timer
aTimer.Enabled = true;
}
public void DoWork(Object source, System.Timers.ElapsedEventArgs e) {
//do work here
}
}

Timer inaccurate

I am trying to implement a delay of 10 seconds before calling a a method. However, the method is being called in just one second.
private void closeDoors(Floor floor)
{
Timer timer = new Timer();
timer.Interval = 10000;
timer.Tick += delegate
{
DoorManager(floor, Operation.CLOSE, null);
};
timer.Start();
}
Where am I going wrong?
Thank you for your assistant.
Your problem may occur because of not stopping the Timer after finishing its job. The following modified code should work (as long as I've experienced with Timer):
private void closeDoors(Floor floor) {
Timer timer = new Timer();
timer.Interval = 10000;
timer.Tick += (s,e) => {
DoorManager(floor, Operation.CLOSE, null);
((Timer)s).Stop();
};
timer.Start();
}
I manage to fix it by incrementing the timer Interval as the time delay was being utilised by a process invoked by another method call insideDoorManager().

Timer object in a class library?

I tried following code to run timer in class library but timer_Elapsed wasn't fired. I also tried using timer from System.Windows.Forms but it didn't worked.
private static void SetTimer(DateTime dateTime)
{
timer = new System.Timers.Timer();
TimeSpan timeSpan = dateTime - DateTime.Now;
timer.Interval = timeSpan.Milliseconds;
timer.Elapsed += new System.Timers.ElapsedEventHandler(timer_Elapsed);
timer.Enabled = true;
timer.Start();
}
private static void timer_Elapsed(object myobject, System.Timers.ElapsedEventArgs e)
{
timer.Enabled = false;
timer.Stop();
Start(_appCastURL, _remindLaterAt, _remindLaterFormat);
}
A forms based timer won't work, it requires an active message pump to run in order to process the tick events.
The System.Timers.Timer will work as intended, but only if you Start it or enable it (via Enabled = true). Note that the Elapsed event will fire on an arbitrary ThreadPool thread by default. You can use the SynchronizingObject property in order to control the thread the event runs on.
You will have to .Start() it :)
Removed Static from the timer declaration and remove static from event and SetTimer method, put it in the class extending Form in the class library and it worked.
private void SetTimer(DateTime remindLater)
{
timer = new System.Timers.Timer();
TimeSpan timeSpan = remindLater - DateTime.Now;
timer.Interval = (int) timeSpan.TotalMilliseconds;
timer.Elapsed += new System.Timers.ElapsedEventHandler(timer_Elapsed);
timer.Start();
}
private void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
timer.Stop();
AutoUpdater.Start(appCast, remindLaterAt, remindLaterFormat);
}
Try to use the System.Threading.Timer

Fire timer_elapsed immediately from OnStart in windows service

I'm using a System.Timers.Timer and I've got code like the following in my OnStart method in a c# windows service.
timer = new Timer();
timer.Elapsed += timer_Elapsed;
timer.Enabled = true;
timer.Interval = 3600000;
timer.Start();
This causes the code in timer_Elapsed to be executed every hour starting from an hour after I start the service. Is there any way to get it to execute at the point at which I start the service and then every hour subsequently?
The method called by timer_Elapsed takes too long to run to call it directly from OnStart.
Just start a threadpool thread to call the worker function, just like Timer does. Like this:
timer.Elapsed += timer_Elapsed;
ThreadPool.QueueUserWorkItem((_) => DoWork());
...
void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e) {
DoWork();
}
void DoWork() {
// etc...
}
Use AutoReset Property of System.Timers.Timer and set it value to "true".
No need to use timer.Start() because it does the same job as timer.Enabled = true;
timer = new Timer();
timer.Elapsed += timer_Elapsed;
timer.Enabled = true;
timer.Interval = 3600000;
timer.AutoReset = true;
AutoReset = true will set a value indicating that the Timer should raise the Elapsed event each time when the specified interval elapses.
If you want your Timer to be fired immediately then you could simply just initialize the Timer object without a specified interval (it will default to 100ms which is almost immediately :P), then set the interval within the called function to whatever you like. Here is an example of what I use in my Windows Service:
private static Timer _timer;
protected override void OnStart(string[] args)
{
_timer = new Timer(); //This will set the default interval
_timer.AutoReset = false;
_timer.Elapsed = OnTimer;
_timer.Start();
}
private void OnTimer(object sender, ElapsedEventArgs args)
{
//Do some work here
_timer.Stop();
_timer.Interval = 3600000; //Set your new interval here
_timer.Start();
}
Use System.Threading.Timer class instead of System.Timers.Timer as this type is just a wrapper for Threading Timer.
It also suits your requirement.
System.Threading.Timer timer =
new System.Threading.Timer(this.DoWork, this, 0, 36000);
Here are the details.

How to stop a timer after it is done running?

I have a Console App and in the main method, I have code like this:
Timer time = new Timer(seconds * 1000); //to milliseconds
time.Enabled = true;
time.Elapsed += new ElapsedEventHandler(time_Elapsed);
I only want the timer to run once so my idea is that I should stop the timer in the time_Elapsed method. However, since my timer exists in Main(), I can't access it.
You have access to the Timer inside of the timer_Elapsed method:
public void timer_Elapsed(object sender, ElapsedEventArgs e)
{
Timer timer = (Timer)sender; // Get the timer that fired the event
timer.Stop(); // Stop the timer that fired the event
}
The above method will stop whatever Timer fired the Event (in case you have multiple Timers using the same handler and you want each Timer to have the same behavior).
You could also set the behavior when you instantiate the Timer:
var timer = new Timer();
timer.AutoReset = false; // Don't reset the timer after the first fire
A little example app:
static void Main(string[] args)
{
int seconds = 2;
Timer time = new Timer(seconds * 1000); //to milliseconds
time.Enabled = true;
time.Elapsed += new ElapsedEventHandler(MyHandler);
time.Start();
Console.ReadKey();
}
private static void MyHandler(object e, ElapsedEventArgs args)
{
var timer = (Timer) e;
timer.Stop();
}
I assume that you're using System.Timers.Timer rather than System.Windows.Forms.Timer?
You have two options.
First, as probably the best, is to set the AutoReset property to false. This should do exactly what you want.
time.AutoReset = false;
The other option is to call Stop in the event handler.
You may also use the System.Threading.Timer. Its constructor takes two time-related parameters:
The delay before the first "tick" (due time)
The period
Set the period to Timeout.Infinite to prevent from firing again.

Categories