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).
Related
(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...
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
What I want to do. I want to SomeMethod will be called periodically. Therefore, I want to timer will be started from backgroung thread after body of background thread method is passed. _timer.Start() was invoked, but TickHandler doesn't;
code:
using Timer = System.Windows.Forms.Timer;
class TestTimer
{
private Timer _timer;
private Thread _thread;
public TestTimer()
{
// create and initializing timer. but not started!
_timer = new Timer();
_timer.Tick += TickHandler;
_timer.Interval = 60000; // 1 minute
// create and start new thread
_thread = new Thread(SomeMethod);
_thread.Start();
}
private void TickHandler(object sender, EventArgs e)
{
// stop timer
_timer.stop();
//some handling
// run background thread again
_thread = new Thread(SomeMethod);
_thread.Start();
}
private void SomeMethod()
{
// some operations
// start timer!
TimerStart();
}
private void TimerStart()
{
_timer.Start();
}
}
By monkey method I found if add Delegate like this
internal delegate void TimerDelegate();
And replace string
TimerStart();
with
Application.Current.Dispatcher.Invoke(new TimerDelegate(TimerStart), null);
all works fine. Somebody can explain me what is the trick?
You've got things mixed up a bit.
If you want a timer that fires on a background thread, you don't have to create a thread to start it (it doesn't matter which thread calls the Start method). Just use System.Timers.Timer, and each Elapsed event will occur on a thread-pool thread.
If you want a timer that fires on the UI thread, since it looks like you're using WPF, you should use System.Windows.Threading.DispatcherTimer, and not the Windows Forms timer you've been using. You should create the timer (i.e. call new) on a particular UI thread, and every Tick event will occur on that thread. Again, it doesn't matter from which thread you call Start.
Here's an explanation of what's happening in your code: You're starting a Windows Forms timer on a non-UI thread. This kind of timer requires a message pump to be running on that thread so it can receive messages. Because it's a non-UI thread, there's no message pump. When you used the Dispatcher.Invoke method, you marshaled the creation of the timer back to the application's main UI thread, which made it work. But it is all quite redundant. If you want to keep the code as is, just replace the timer with a DispatcherTimer, and then you'll be able to remove the Invoke call.
Alternatively, if you're using .NET 4.5 you could use await/async to make this all much easier (be sure to call SomeMethod from the UI thread):
async Task SomeMethod(CancellationToken ct)
{
while (!ct.IsCancellationRequested)
{
await Task.Run(() => DoAsyncStuff(), ct);
DoUIStuff();
await Task.Delay(TimeSpan.FromMinutes(1), ct);
}
}
MSDN can explain it for you:
Note The Windows Forms Timer component is single-threaded, and is
limited to an accuracy of 55 milliseconds. If you require a
multithreaded timer with greater accuracy, use the Timer class in the
System.Timers namespace.
Let me start from saying that it's more a question than a problem that needs to be solved. I have the solution now and things work fine for me. But I wonder why problem occured first time.
This is the code I have right now and it works like I expect:
private void OnNewGameStarted(Game game)
{
_activeGames.Add(game);
TimeSpan delay = game.GetTimeLeft();
var timer = new Timer(delay.TotalMilliseconds) {AutoReset = false};
timer.Elapsed += (sender, args) => GameEndedCallback(game);
timer.Start();
}
private void GameEndedCallback(Game game)
{
if (_statisticsManager.RegisterGame(game))
_gamesRepository.Save(game);
_gameStatusSubscriber.GameStatusChanged(game);
}
I used to use System.Threading.Timer instead of System.Timers.Timer and sometimes timer event (GameEndedCallback method) fired and sometimes not. I couldn't find any reason why it was that way.
This is the code I used to initilize timer (other parts are the same):
TimeSpan delay = game.GetTimeLeft();
new Timer(GameEndedCallback,game,(int)delay.TotalMilliseconds,Timeout.Infinite);
}
private void GameEndedCallback(object state)
{
var game = (Game) state;
Method OnNewGameStarted is event handler and it is called after chain of methods from Fleck webserver when some certain message comes to it.
There is a post about the 3 timer types and what they do.
the main things are:
System.Timers.Timer is for multithreading work
System.Windows.Forms.Timer - from the application UI thread
System.Threading.Timer - not always thread safe!
Timeout.Infinite is The time interval between invocations of callback, in milliseconds. Specify Timeout.Infinite to disable periodic signaling. See MSDN: http://msdn.microsoft.com/en-us/library/2x96zfy7.aspx
Timeout.Infinite is a constant used to specify an infinite waiting period.
Try this to get perodic calls to the callback
new System.Threading.Timer(GameEndedCallback, game, (int)delay.TotalMilliseconds, (int)delay.TotalMilliseconds);
I want to repeat a function from the moment the program opens until it closes every few seconds.
What would be the best way to do this in C#?
Use a timer. There are 3 basic kinds, each suited for different purposes.
System.Windows.Forms.Timer
Use only in a Windows Form application. This timer is processed as part of the message loop, so the the timer can be frozen under high load.
System.Timers.Timer
When you need synchronicity, use this one. This means that the tick event will be run on the thread that started the timer, allowing you to perform GUI operations without much hassle.
System.Threading.Timer
This is the most high-powered timer, which fires ticks on a background thread. This lets you perform operations in the background without freezing the GUI or the main thread.
For most cases, I recommend System.Timers.Timer.
For this the System.Timers.Timer works best
// Create a timer
myTimer = new System.Timers.Timer();
// Tell the timer what to do when it elapses
myTimer.Elapsed += new ElapsedEventHandler(myEvent);
// Set it to go off every five seconds
myTimer.Interval = 5000;
// And start it
myTimer.Enabled = true;
// Implement a call with the right signature for events going off
private void myEvent(object source, ElapsedEventArgs e) { }
See Timer Class (.NET 4.6 and 4.5) for details
Use a timer. Keep in mind that .NET comes with a number of different timers. This article covers the differences.
There are lot of different Timers in the .NET BCL:
System.Timers.Timer
System.Threading.Timer
System.Windows.Forms.Timer
System.Web.UI.Timer
System.Windows.Threading.DispatcherTimer
When to use which?
System.Timers.Timer, which fires an event and executes the code in one or more event sinks at regular intervals. The class is intended for use as a server-based or service component in a multithreaded environment; it has no user interface and is not visible at runtime.
System.Threading.Timer, which executes a single callback method on a thread pool thread at regular intervals. The callback method is defined when the timer is instantiated and cannot be changed. Like the System.Timers.Timer class, this class is intended for use as a server-based or service component in a multithreaded environment; it has no user interface and is not visible at runtime.
System.Windows.Forms.Timer (.NET Framework only), a Windows Forms component that fires an event and executes the code in one or more event sinks at regular intervals. The component has no user interface and is designed for use in a single-threaded environment; it executes on the UI thread.
System.Web.UI.Timer (.NET Framework only), an ASP.NET component that performs asynchronous or synchronous web page postbacks at a regular interval.
System.Windows.Threading.DispatcherTimer, a timer that's integrated into the Dispatcher queue. This timer is processed with a specified priority at a specified time interval.
Source
Some of them needs explicit Start call to begin ticking (for example System.Timers, System.Windows.Forms). And an explicit Stop to finish ticking.
using TimersTimer = System.Timers.Timer;
static void Main(string[] args)
{
var timer = new TimersTimer(1000);
timer.Elapsed += (s, e) => Console.WriteLine("Beep");
Thread.Sleep(1000); //1 second delay
timer.Start();
Console.ReadLine();
timer.Stop();
}
While on the other hand there are some Timers (like: System.Threading) where you don't need explicit Start and Stop calls. (The provided delegate will run a background thread.) Your timer will tick until you or the runtime dispose it.
So, the following two versions will work in the same way:
using ThreadingTimer = System.Threading.Timer;
static void Main(string[] args)
{
var timer = new ThreadingTimer(_ => Console.WriteLine("Beep"), null, TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(1));
Console.ReadLine();
}
using ThreadingTimer = System.Threading.Timer;
static void Main(string[] args)
{
StartTimer();
Console.ReadLine();
}
static void StartTimer()
{
var timer = new ThreadingTimer(_ => Console.WriteLine("Beep"), null, TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(1));
}
But if your timer disposed then it will stop ticking obviously.
using ThreadingTimer = System.Threading.Timer;
static void Main(string[] args)
{
StartTimer();
GC.Collect(0);
Console.ReadLine();
}
static void StartTimer()
{
var timer = new ThreadingTimer(_ => Console.WriteLine("Beep"), null, TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(1));
}