Timer never stops - c#

I call Stop() from Tick callback event function but it doesn't stop and that function run over and over. Why is and how do I fix this?
This function is called once only:
System.Windows.Forms.Timer timer1 = new System.Windows.Forms.Timer();
void foo() {
timer1.Interval = 1000;
timer1.Tick += new EventHandler(timerTick);
timer1.Start();
}
and the callback function:
void timerTick(object o, EventArgs ea)
{
if (browser.ReadyState == WebBrowserReadyState.Complete)
{
MessageBox.Show("stop it!");
timer1.Stop();
}
}
This is going to show an infinity of stop it Messages Boxes while it must be show once.

You need to reverse your statements:
if (browser.ReadyState == WebBrowserReadyState.Complete)
{
timer1.Stop();
MessageBox.Show("stop it!");
}
As it stands; it will keep ticking until you close a box (since MessageBox.Show blocks), which could be a lot of ticks.

Another way to do it is use a System.Timers.Timer instead. You can tell that timer to run once and not restart until you tell it to.
System.Timers.Timer timer1 = new System.Timers.Timer();
void foo() {
timer1.Interval = 1000;
timer1.Elapsed += new ElapsedEventHandler(timerTick);
//This assumes that the class `foo` is in is a System.Forms class. Makes the callback happen on the UI thread.
timer1.SynchronizingObject = this;
//Tells it to not restart when it finishes.
timer1.AutoReset = false;
timer1.Start();
}
void timerTick(object o, ElapsedEventArgs ea)
{
if (browser.ReadyState == WebBrowserReadyState.Complete)
{
MessageBox.Show("stop it!");
}
}

Related

Timer does not fire in a multi-thread form

I have a System.Timers.Timer timer in a form. Also I have a thread that reads from an RFID device (with function: GetData()). I want to limit the time of my thread with a timer, but the timer does not fire.
System.Threading.Thread GetData;
System.Timers.Timer timer = new System.Timers.Timer();
int reverseCounter=1000;
public CardDragMaifareFrm()
{
timer.Elapsed += new ElapsedEventHandler(timer_Elapsed);
timer.Interval = 10;
timer.Enabled = true;
timer.Start();
GetData = new Thread(new ThreadStart(ReadCardData));
GetData.Start();
}
void timer_Elapsed(object sender, EventArgs e)
{
if (reverseCounter > 0)
{
MessageBox.Show("hey");
reverseCounter -= 1;
}
else
{// some actions for terminating GetData thread}
}
but I don't see "hey" message... can anybody help me? thanx
I used the first rule of computer engineering: Restart it, maybe it will work"... ;-)

System.Timers.Timer() Firing multiple times due to aggregation of Elapsed Events

I want to have a section of my code start a timer once it's called, and I want this timer to keep running until I quit the whole program. My problem is, each time I call OnSomethingHappens() , the Elapsed events aggregate (despite my effort with -= ) and the timer starts firing one extra time (or at least this is what I think is happening). I have also tried defining the timer within the class, to no avail. Here's the related part of my code:
public override void OnSomethingHappens()
{
Timer aTimer= new System.Timers.Timer();
aTimer.Elapsed -= (sender, e) => DoSomethingElse(sender, e);
aTimer.Stop();
aTimer.Close();
aTimer.Elapsed += (sender, e) => DoSomethingElse(sender, e);
aTimer.Interval = 1000;
aTimer.AutoReset = true; // I want the timer to keep working, but only fire once each time
Console.WriteLine("Enabling Timer aTimer");
aTimer.Start();
}
I cannot use static (not sure how that would help but I saw timers being defined as static in many sources) because this class has many instances, and I want them to have separate timers.
Thank you.
Start your timer without the AutoReset and restart it at the end of the DoSomethingElse.
aTimer.AutoReset = false;
aTimer.Start();
DoSomethingElse(..)
{
// do stuff here
aTimer.Start();
}
if each instance of this class uses his own timer , so static is no needed.
private Timer _aTimer;
public void OnSomethingHappens()
{
if (_aTimer != null)
{
_aTimer.Enabled = true; // start timer
return;
}
_aTimer = new System.Timers.Timer();
_aTimer.Elapsed += DoSomethingElse;
_aTimer.Interval = 1000; // every 1 second
_aTimer.Enabled = true; // start timer
}
private void DoSomethingElse(object sender, ElapsedEventArgs e)
{
_aTimer.Enabled = false; // stop timer
// do w/e you want
}
First thing you should really only create once instance of the timer, and hook up one event listener. With your current code, a new timer is being created, with an event listener, every time the method is called. Instead make the timer a class variable, and hook up the event listener in the constructor.
You can start the timer in the OnSomethingHappens, but what do you want to happen on subsequent calls to the method? Should the timer restart, or just continue?
You would probably also want to make the class IDisposable, or at least provide a Stop method to stop the timer when the application closes.
public class MyClass : MyBaseClass, IDisposable
{
private Timer _timer;
private volatile bool _isStopped = true;
public MyClass()
{
_timer = new Timer();
_timer.Interval = 1000;
_timer.Elapsed = OnTimerElapsed;
}
public void Stop()
{
_isStopped = true;
_timer.Stop();
}
public void Dispose()
{
if (_timer != null)
{
Stop();
_timer = null;
}
}
protected override void OnSomethingHappens()
{
if (_timer.Enabled)
{
// Restart or do nothing if timer is already running?
}
else
{
_isStopped = false;
_timer.Start();
}
}
private void OnTimerElapsed(object sender, EventArgs a)
{
if (_isStopped)
{
// If the Stop method was called after the Elapsed event was raised, don't start a long running operation
return;
}
}
}

changing text of button with timeout in c#

How can I change the text of button with timeout? I tried out with the following code but it is not working.
private void button1_Click(object sender, EventArgs e)
{
Stopwatch sw = new Stopwatch();
sw.Start();
if (button1.Text == "Start")
{
//do something
button1.Text = "stop"
if (sw.ElapsedMilliseconds > 5000)
{
button1.Text = "Start";
}
}
How can I correct my code?
You need to use Timer instead:
Timer t = new Timer(5000); // Set up the timer to trigger on 5 seconds
t.SynchronizingObject = this; // Set the timer event to run on the same thread as the current class, i.e. the UI
t.AutoReset = false; // Only execute the event once
t.Elapsed += new ElapsedEventHandler(t_Elapsed); // Add an event handler to the timer
t.Enabled = true; // Starts the timer
// Once 5 seconds has elapsed, your method will be called
void t_Elapsed(object sender, ElapsedEventArgs e)
{
// The Timer class automatically runs this on the UI thread
button1.Text = "Start";
}
Stopwatch is only for measuring how much time has passed since you called Start().
If you're using C# 5
private async void button1_Click(object sender, EventArgs e)
{
button1.Text = "Stop";
await Task.Delay(5000);
button1.Text = "Start";
}
You could use a timer. In this example the text of the button changes to "Stop" after 5 seconds.
private Timer timer = new Timer();
private void button1_Click(object sender, EventArgs e)
{
timer.Interval = 5000; // interval length
timer.Tick += TimerOnTick;
timer.Enabled = true; // activate timer
button1.Text = "Start";
}
private void TimerOnTick(object sender, EventArgs eventArgs)
{
timer.Enabled = false; // deactivate timer
button1.Text = "Stop";
}
I think you can reach your goal by using Timer
Example of using Timer
public partial class FormWithTimer : Form
{
Timer timer = new Timer();
public FormWithTimer()
{
InitializeComponent();
// Everytime timer ticks, timer_Tick will be called
timer.Tick += new EventHandler(timer_Tick);
timer.Interval = (1000) * (1); // Timer will tick every second
timer.Enabled = true; // Enable the timer
}
// .......
showForm() // declaration
{
timer.start();
// .......
timer.stop();
}
void timer_Tick(object sender, EventArgs e)
{
//hide form...through visibility
}
}
Use this instead of Stopwatch:
private void button1_Click(object sender, EventArgs e)
{
button1.Text = "stop"
aTimer = new System.Timers.Timer(5000);
aTimer.Elapsed += new ElapsedEventHandler(OnTimedEvent);
aTimer.Enabled = true;
}
// Specify what you want to happen when the Elapsed event is raised.
private static void OnTimedEvent(object source, ElapsedEventArgs e)
{
button1.Text = "Start";
var atim = source as Timer;
if (atim != null)
atim.Elapsed -= OnTimedEvent;
}

Timer won't tick

I have a Windows.Forms.Timer in my code, that I am executing 3 times. However, the timer isn't calling the tick function at all.
private int count = 3;
private timer;
void Loopy(int times)
{
count = times;
timer = new Timer();
timer.Interval = 1000;
timer.Tick += new EventHandler(timer_Tick);
timer.Start();
}
void timer_Tick(object sender, EventArgs e)
{
count--;
if (count == 0) timer.Stop();
else
{
// Do something here
}
}
Loopy() is being called from other places in the code.
Try using System.Timers instead of Windows.Forms.Timer
void Loopy(int times)
{
count = times;
timer = new Timer(1000);
timer.Enabled = true;
timer.Elapsed += new ElapsedEventHandler(timer_Elapsed);
timer.Start();
}
void timer_Elapsed(object sender, ElapsedEventArgs e)
{
throw new NotImplementedException();
}
If the method Loopy() is called in a thread that is not the main UI thread, then the timer won't tick.
If you want to call this method from anywhere in the code then you need to check the InvokeRequired property. So your code should look like (assuming that the code is in a form):
private void Loopy(int times)
{
if (this.InvokeRequired)
{
this.Invoke((MethodInvoker)delegate
{
Loopy(times);
});
}
else
{
count = times;
timer = new Timer();
timer.Interval = 1000;
timer.Tick += new EventHandler(timer_Tick);
timer.Start();
}
}
I am not sure what you are doing wrong it looks correct, This code works: See how it compares to yours.
public partial class Form1 : Form
{
private int count = 3;
private Timer timer;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
Loopy(count);
}
void Loopy(int times)
{
count = times;
timer = new Timer();
timer.Interval = 1000;
timer.Tick += new EventHandler(timer_Tick);
timer.Start();
}
void timer_Tick(object sender, EventArgs e)
{
count--;
if (count == 0) timer.Stop();
else
{
//
}
}
}
Here's an Rx ticker that works:
Observable.Interval(TimeSpan.FromSeconds(1))
.Take(3)
.Subscribe(x=>Console.WriteLine("tick"));
Of course, you can subscribe something more useful in your program.
you may have started the timer from another thread, so try invoking it from the correct thread.
for example, instead of:
timerX.start();
Use:
Invoke((MethodInvoker)delegate { timerX.Start(); });
Check if your timer in properties is enabled.
Mine was false and after setting to true it worked.
If you are using Windows.Forms.Timer then should use something like following.
//Declare Timer
private Timer _timer= new Timer();
void Loopy(int _time)
{
_timer.Interval = _time;
_timer.Enabled = true;
_timer.Tick += new EventHandler(timer_Elapsed);
_timer.Start();
}
void timer_Elapsed(object sender, EventArgs e)
{
//Do your stuffs here
}
If you use some delays smaller than the interval inside the timer, the system.timer will execute other thread and you have to deal with a double thread running at the same time. Apply an InvokeRequired to control the flow.

c# Timer Stop Confusion

I would like to set a textbox text to "blink" by changing text colors when a button is clicked.
I can get the text to blink how I want it to, but I want it to stop after a few blinks. I cannot figure out how to make it stop after the timer fires a few times.
Here is my code:
public Form1()
{
InitializeComponent();
Timer timer = new Timer();
timer.Interval = 500;
timer.Enabled = false;
timer.Start();
timer.Tick += new EventHandler(timer_Tick);
if (timerint == 5)
timer.Stop();
}
private void timer_Tick(object sender, EventArgs e)
{
timerint += 1;
if (textBoxInvFooter.ForeColor == SystemColors.GrayText)
textBoxInvFooter.ForeColor = SystemColors.Highlight;
else
textBoxInvFooter.ForeColor = SystemColors.GrayText;
}
I know my problem lies with how I'm using the "timerint", but I'm not sure where to put it, or what solution I should use...
Thank you for all your help!
You just have to put the timer check inside the Tick handler. You can access the Timer object by using the sender argument of the handler.
private void timer_Tick(object sender, EventArgs e)
{
// ...
timerint += 1;
if (timerint == 5)
{
((Timer)sender).Stop();
}
}
Here's the complete code that I would use to solve your issue. It correctly stops the timer, detaches the event handler, and disposes the timer. It disables the button during the flashing, and also restores the colour of the textbox after the five flashes are complete.
The best part is that it is purely defined within the one lambda, so no class-level variables required.
Here it is:
button1.Click += (s, e) =>
{
button1.Enabled = false;
var counter = 0;
var timer = new Timer()
{
Interval = 500,
Enabled = false
};
EventHandler handler = null;
handler = (s2, e2) =>
{
if (++counter >= 5)
{
timer.Stop();
timer.Tick -= handler;
timer.Dispose();
textBoxInvFooter.ForeColor = SystemColors.WindowText;
button1.Enabled = true;
}
else
{
textBoxInvFooter.ForeColor =
textBoxInvFooter.ForeColor == SystemColors.GrayText
? SystemColors.Highlight
: SystemColors.GrayText;
}
};
timer.Tick += handler;
timer.Start();
};

Categories