Implement a pausable, "ticking" stopwatch [duplicate] - c#

(My first question here!)
Hi, I am kind of beginner in c#. I tried to build a simple timer (in Windows.Forms).
I made a label which indicates the time, and used the StopWatch class (from system.diagnostics). The trigger event for starting / stopping the stopwatch is the spacebar KeyDown event. After the second tap the stopwatch stops and Label.text is assigned to the Stopwatch.Elapsed value. I want to continuously update the label, but I don't know how.
If I make while(StopWatchName.IsRunning) in the event itself, the event will indefinitely continue and won't respond for the second tap.
Thanks in advance for any ideas!

You should probably have a timer which fires frequently (e.g. every 10ms) - start the timer when you start the stopwatch, and stop the timer when you stop the stopwatch. The timer tick event would just set the label's Text property from the stopwatch.
The timer's interval won't be exact of course - but that's okay, because the point is to rely on the stopwatch for the actual timing. The timer is just there to update the label frequently.

You are probably going to want to use System.Timers. Timer class in order to call a function every few seconds to update your UI with the time elapased value.
Here is a good Sample:
http://msdn.microsoft.com/en-us/library/system.timers.timer.aspx
Basically, your OnTimedEvent event function from the sample is what will accomplish thisin your code.
EDIT: John is correct (see comments) you should be using Forms.Timer you can avoid thread marshaling.
http://msdn.microsoft.com/en-us/library/system.windows.forms.timer.aspx
TimerEventProcessor would be the function of concern in that sample.

The following example instantiates a System.Timers.Timer object that fires its Timer.Elapsed event every two seconds (2,000 milliseconds), sets up an event handler for the event, and starts the timer. The event handler displays the value of the ElapsedEventArgs.SignalTime property each time it is raised. (document)
using System;
using System.Timers;
public class Example
{
private static System.Timers.Timer aTimer;
public static void Main()
{
SetTimer();
Console.WriteLine("\nPress the Enter key to exit the application...\n");
Console.WriteLine("The application started at {0:HH:mm:ss.fff}", DateTime.Now);
Console.ReadLine();
aTimer.Stop();
aTimer.Dispose();
Console.WriteLine("Terminating the application...");
}
private static void SetTimer()
{
// Create a timer with a two second interval.
aTimer = new System.Timers.Timer(2000);
// Hook up the Elapsed event for the timer.
aTimer.Elapsed += OnTimedEvent;
aTimer.AutoReset = true;
aTimer.Enabled = true;
}
private static void OnTimedEvent(Object source, ElapsedEventArgs e)
{
Console.WriteLine("The Elapsed event was raised at {0:HH:mm:ss.fff}",
e.SignalTime);
}
}
// The example displays output like the following:
// Press the Enter key to exit the application...
//
// The application started at 09:40:29.068
// The Elapsed event was raised at 09:40:31.084
// The Elapsed event was raised at 09:40:33.100
// The Elapsed event was raised at 09:40:35.100
// The Elapsed event was raised at 09:40:37.116
// The Elapsed event was raised at 09:40:39.116
// The Elapsed event was raised at 09:40:41.117
// The Elapsed event was raised at 09:40:43.132
// The Elapsed event was raised at 09:40:45.133
// The Elapsed event was raised at 09:40:47.148
//
// Terminating the application...

Related

Can System.Timers.Timer elapsed event if previous event still working?

Can System.Timers.Timer elapsed event if previous event still working?
For example, i set Interval 100 ms, but code in handler works 200 ms.
_taskTimer = new System.Timers.Timer();
_taskTimer.Interval = 100;
_taskTimer.Elapsed += _taskTimer_Elapsed;
void _taskTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
Work(); // works 200 ms.
}
Is timer "wait" while Work() method ends? Or execute a new one?
Thank you!
System.Timers.Timer(Multi Threaded Timer) is multithreaded timer. that means it executes it elapse event on multiple thread and that means it don't wait for previous elapse event.
if you want to wait for previous elapse event to complete that you can use System.Windows.Timer (Single Threaded Timer) - this is single threaded timer will execute event on single thread only(UI thread) which created timer.
You can read more about this here : Timers written by Joe Albahari
Internally system.timers.timer also uses system.threading.timers, so the execution process continues even after elapsed fires new execution.
Have a look at the source code of System.Timers.Timer: Timers.Cs
It will Continue Executing on different thread
For reference you can visit this page

Timers.Timer stopped triggering elapsed event and !Threads showing 1023 unstarted and pending threads

my application has a Timers.Timer implementation as in this question which seems to stop triggering its elapsed event after some time (days or weeks) [the elapsed event is supposed to run every 60 seconds see this for details]
0:000> !threads -live
ThreadCount: 1041
UnstartedThread: 1023
BackgroundThread: 11
PendingThread: 1023
DeadThread: 3
Hosted Runtime: no
Later, we found out that when the the elapsed event stopped getting fired, the number of unstarted and pending threads also rise consistently until 1023 limit is reached. Then the process gets stuck.
What is the cause/reason or the relation between my Timer not firing the event and the eventual rise in the # threads (unstarted and pending)?
Almost certainly your timer event handler is not exiting. Either it's blocking (in a Sleep or waiting on some event), or it's gone into an infinite loop. Then the next timer event comes along and it either blocks or goes into an infinite loop. Etc . . .
You can determine if this is the case by changing your timer event handler so that it tells you if it's re-entered:
private bool _inTimer = false;
private void TimerTick(object Sender, ElapsedEventArgs e)
{
if (_inTimer)
{
// there's already a timer running.
// log a message or notify you in some other way.
}
_inTimer = true;
// do your processing here
// and then clear the flag
_inTimer = false;
}
That will tell you if what I suspect is the case. But don't use it as a production way to prevent concurrent timer instances, though. There's a race condition with the Boolean flag. If you want to prevent concurrent timer ticks, disable the timer when you enter the method, and then re-enable it when you exit. Like this:
private void TimerTick(object Sender, ElapsedEventArgs e)
{
_myTimer.Enabled = false;
// do processing
// then re-enable the timer
_myTimer.Enabled = true;
}
On a related note, the other thing that can cause your timer to appear to stop functioning is that it throws an exception which the runtime library squashes without surfacing. That behavior is documented:
The Timer component catches and suppresses all exceptions thrown by event handlers for the Elapsed event. This behavior is subject to change in future releases of the .NET Framework.
So if an exception goes uncaught in your event handler, it's dropped on the floor. It's for this reason that I recommend against using System.Timers.Timer. I would suggest using System.Threading.Timer instead, as it doesn't suffer from this idiotic design.
I ended up revising/revamping the Timer implementation and use a Thread with a do-while loop, instead. This will avoid the 'unknown' problems we are getting from the Timers elapsed event not firing up.
Thanks all

C# Timer -- measuring time slower

I'm writing a code where:
I.)
The user adds "events" during run-time. (To a flowlayoutpanel) These events are turning some LEDs on/off, after "x" time has elapsed and the LED-turning functions are written in a Led-function.cs class.
i.e:
1) Turn left led on After 3500ms
2) Turn right led on After 4000ms
II.)
When the user hits start a timer starts.
// Create timer.
System.Timers.Timer _timer;
_timer = new System.Timers.Timer();
_timer.Interval = (1);
_timer.Elapsed += (sender, e) => { HandleTimerElapsed(LedObject, device, _timer); };
_timer.Start();
III.)
The timer's tick event is raised every millisecond and checks if the user definied time has ellapsed. Im measuring the elapsed time with adding +1 to an integer at every tick event. (NumberOfTicks++;)
//Timer Handle
private void HandleTimerElapsed(Led_Functions LedObject, string device, System.Timers.Timer _timer)
{
NumberOfTicks++;
if (NumberOfTicks >= Start_time[0])
{
LedObject.LeftLED_ONnobutton(device);
}
}
IV.) What I noticed was that when the tick was set to 1. (So the tick event is raised every millisecond) Even if I set 3000ms to the evet the LED actually flashed around 6 seconds.
When the tick was set to 100. (So every 0,1s) then the flash was more accurate (3,5sec or so).
Any Ideas why im having this delay in time?
Or do you have any ideas how could I implement it better?
Thank you!
1ms is a really small interval for CPUs. You cannot ensure your code get called every 1ms especially when the system has some heavy work to do.
A better implement is to use DateTime.Now - startTime to get the time span or use Stopwatch.
private Stopwatch stopwatch = new Stopwatch();
// start the stopwatch:
stopwatch.Start();
// Timer Handle:
numberOfTicks = stopwatch.ElapsedMilliseconds;

Initial Form of C# program unavailable while the program is running

I am having a problem getting the main Form in my program to run as I want. I am using C#. On my initial main form (Form1) I have a command button that runs a long program. In the middle of the program I want the user to be able go back to the initial form and click on some new checkboxes that I will place on that initial form from within the C# program. The code below just freezes the initial form. I do not need to get the code below to work exactly. I just need it to allow me to access the main initial form in the middle of the program that I started with the command button.
To do this I have an infinite while loop that calls the timer. Is this the correct way to do this? I do not need the program below to work. I just need to be able to access that initial Form in the middle of the program. Since it is not working it seems that it is not the way to do this but what is the correct way?
The following code runs the OnTimedEvent function (method) below. The function used to put up a Messagebox but I commented that out. I do NOT need that function to work. It is only there for testing purposes. My goal is that I need the initial main Form to allow me to enter more information while it is running from the command button. The function below runs about 15 times and I get the error
Exception of type 'System.OutOfMemoryException' was thrown.
on the line aTimer.Elapsed += new ElapsedEventHandler(OnTimedEvent);
The code is below:
System.Timers.Timer aTimer;
// Create a timer with a one second interval.
aTimer = new System.Timers.Timer(100);
while (true)
{
// Hook up the event handler for the Elapsed event.
aTimer.Elapsed += new ElapsedEventHandler(OnTimedEvent);
// Only raise the event the first time Interval elapses.
aTimer.AutoReset = false;
aTimer.Enabled = true; // uncommented this now
//addded below
aTimer.Start();
}
I have tried it in several different ways but the main Form always just freezes. I just want to be able to select things (checkboxes, for instance) on the main Form (Form1) so the below code may not be needed. The timer above calls OnTimedEvent which is below.
private static void OnTimedEvent(object source, ElapsedEventArgs e)
{
// MessageBox.Show("Hello World");
}
In many places on the web I have seen (including stackoverflow) that I should be using timers to get the main initial Form to be useable but the code above just causes the Form to be Frozen and I get the bar at the top of the form indicating that it is Not Responding.
I am using Windows XP and Visual Studio 2008. As I indicated above I am using C#.
To summarize, is the above code the correct way to get the main, Initial form to be available after a command button has been running? If it is, what am I doing wrong? If this is not the correct way, what is?
BTW, I asked a completely unrelated question about this project here
Any ideas?
You should simply remove the while loop
System.Timers.Timer aTimer;
// Create a timer with a one second interval.
aTimer = new System.Timers.Timer(1000);
// Hook up the event handler for the Elapsed event.
aTimer.Elapsed += new ElapsedEventHandler(OnTimedEvent);
// Only raise the event the first time Interval elapses.
aTimer.AutoReset = false;
aTimer.Enabled = true; // uncommented this now
//addded below
aTimer.Start();
Timer runs on a separate Thread when you start it. Your while loop just keeps starting the timer over and over again.
System.Timers.Timer
To do this I have an infinite while loop that calls the timer. Is this the correct way to do this?
No. The while loop blocks the UI thread, which in turn makes the program freeze. There's no reason to have the while loop as you're already using a timer to trigger the event.
Without seeing your full, actual, code it's hard to say, but the tradtional method of doing a long-running process without locking the UI is to use Threading in C#.
Can you do your long running action in its own thread so that you don't lock up the UI thread?
Here's a tutorial: http://msdn.microsoft.com/en-us/library/aa645740(v=vs.71).aspx
Don't use a while loop. If you want to run your OnTimedEvent method once a second, use something more like this:
Timer myTimer = new Timer();
myTimer.Elapsed += new ElapsedEventHandler(OnTimedEvent);
myTimer.Interval = 1000; // 1000 ms is one second
myTimer.Enabled = true;
myTimer.Start();

Do System.Timers.Timer run in independent Threads?

I'm trying to understand when the System.Timers.Timer raises the elapsed event, is it raised in an independent thread?
My example below seems to suggest that the three timers run independently in their own threads:
class Program
{
static System.Timers.Timer timer = new System.Timers.Timer();
static System.Timers.Timer timer2 = new System.Timers.Timer();
static System.Timers.Timer timer3 = new System.Timers.Timer();
static void Main(string[] args)
{
timer.Elapsed += new System.Timers.ElapsedEventHandler(
timer_Elapsed);
timer2.Elapsed += new System.Timers.ElapsedEventHandler(
timer2_Elapsed);
timer3.Elapsed += new System.Timers.ElapsedEventHandler(
timer3_Elapsed);
timer.Interval = 1000;
timer2.Interval = 1000;
timer3.Interval = 1000;
timer.Start();
timer2.Start();
timer3.Start();
Console.WriteLine("Press \'q\' to quit the sample.");
while (Console.Read() != 'q') ;
}
static void timer3_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
timer3.Stop();
Console.WriteLine("Timer 3 Hit...");
timer3.Start();
}
static void timer2_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
timer2.Stop();
Console.WriteLine("Timer 2 Hit...");
Thread.Sleep(2000);
timer2.Start();
}
static void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
timer.Stop();
Console.WriteLine("Timer 1 Hit...");
Thread.Sleep(10000);
timer.Start();
}
}
According to the MSDN, on System.Timers.Timer when the Elapsed event fires it is called on a thread in the system thread-pool:
If the SynchronizingObject property is Nothing, the Elapsed event is raised on a ThreadPool thread. If processing of the Elapsed event lasts longer than Interval, the event might be raised again on another ThreadPool thread. In this situation, the event handler should be reentrant.
Since the default value of SynchronizingObject is null, then all your elapsed events would be handled on the thread pool. So, it depends how full the thread pool is, if there are free threads, then each elapsed event can most likely run concurrently on separate threads. If for some reason, though, the system thread-pool is already fully in use, it's possible the elapsed events could be serialized as they are scheduled.
The main point is: "it depends." That is, they will be allowed to run in parallel as long as there are free threads in the pool.
Reference: MSDN on System.Timers.Timer
Based on your code they must be, since Thread.Sleep is a blocking call. None of the other timers would fire if they were running on the same thread.
You could output System.Threading.Thread.CurrentThread.ManagedThreadId in each one to know for sure.
It's quite complex. The documentation says the following:
The server-based Timer is designed for use with worker threads in a multithreaded environment. Server timers can move among threads to handle the raised Elapsed event, resulting in more accuracy than Windows timers in raising the event on time.
and then this:
If the SynchronizingObject property is null, the Elapsed event is raised on a ThreadPool thread. If processing of the Elapsed event lasts longer than Interval, the event might be raised again on another ThreadPool thread. In this situation, the event handler should be reentrant.
and then this:
If you use the Timer with a user interface element, such as a form or control, without placing the timer on that user interface element, assign the form or control that contains the Timer to the SynchronizingObject property, so that the event is marshaled to the user interface thread.
So, there's no simple answer to your question "is it raised in an independent thread?" It depends on many things.
Yes, each time Elapsed is called, the callback is fired on its own thread.
In addition, there is nothing stopping one Elapsed event handler from firing before the previous one is completed. For instance, if your timer fires every 500 milliseconds, but the Elapsed event handler code takes 2 seconds to complete, the Elapsed code can be accessing the same resources (non thread-safe objects, files, etc).

Categories

Resources