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
Related
I have a question about the timer. Does interval time count time of callback executions? I mean for example - I have a timer set to fire every 15 seconds and it executes a callback function that lasts approximately 3 seconds in time. When the next time the timer will fire? In 18 seconds (after callback completes) or after 15 seconds (without waiting for callback)???
Thanks in advance
It will fire every 15 seconds regardless of the callback execution time. If you want it to include the callback execution time, you can suspend and restart the timer in the callback as follows;
At the start:
someTimer.Change(Timeout.Infinite, Timeout.Infinite)
.. and at the end, change it back with the same method:
someTimer.Change(TimeSpan.FromSeconds(15), TimeSpan.FromSeconds(15))
It will fire every 15 secs. Any delays by the callback do not affect the timer. The callback executes on a separate ThreadPool thread. From the docs
The method does not execute on the thread that created the timer; it executes on a ThreadPool thread supplied by the system.
If you want to take the processing time into account, you would have to manage the timer yourself - start a single-fire timer and reset it from inside the callback, eg:
TimerCallback tcb = MyCallBack;
//Start the timer once after 15 secs
_timer=new Timer(tcb,null,TimeSpan.FromSeconds(15),TimeSpan.Infinite);
...
void MyCallBack(Object stateInfo)
{
....
//Reset the timer
_timer.Change(TimeSpan.FromSeconds(15),TimeSpan.Infinite);
}
An easier and cleaner way is to use async/await to wait X seconds after each asynchronous execution. For example, the following code will execute a method 15 secs after its last execution:
while(...)
{
await Task.Delay(TimeSpan.FromSeconds(15));
var response=await Task.Run(()=>someMethod());
...
}
or, if you want to execute code that is already asynchronous
while(...)
{
await Task.Delay(TimeSpan.FromSeconds(15));
await myHttpClient.GetStringAsync(someURL);
}
Under the hood, Task.Delay creates a single-fire timer and completes when the timer finishes. It's almost the same thing you would do manually.
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
I'm really struggling with this. I'm creating a winforms application in visual studio and need a background timer that ticks once every half hour - the purpose of this is to pull down updates from a server.
I have tried a couple of different approaches but they have failed, either due to poor tutorial/examples, or to my own shortcomings in C#. I think it would be a waste of time to show you what I have tried so far as it seems what I tried was pretty far off the mark.
Does anyone know of a clear and simple way of implementing an asynchronous background timer that is easily understandable by a C# newbie?
// Create a 30 min timer
timer = new System.Timers.Timer(1800000);
// Hook up the Elapsed event for the timer.
timer.Elapsed += OnTimedEvent;
timer.Enabled = true;
...
private static void OnTimedEvent(object source, ElapsedEventArgs e)
{
// do stuff
}
with the usual caveats of: timer won't be hugely accurate and might need to GC.KeepAlive(timer)
See also: Why does a System.Timers.Timer survive GC but not System.Threading.Timer?
Declare member variable in your form:
System.Timers.Timer theTimer;
On form load (or whatever other time you need to start update polling), do:
theTimer = new System.Timers.Timer(1800000);
theTimer.Elapsed += PollUpdates;
theTimer.Start();
Declare your PollUpdates member function like this:
private void PollUpdates(object sender, EventArgs e)
{
}
I think you need to know about all timer classes. See Jon's answer below.
What kind of timer are you using?
System.Windows.Forms.Timer will execute in the UI thread
System.Timers.Timer executes in a thread-pool thread unless you
specify a SynchronizingObject
System.Threading.Timer executes its callback in a thread-pool thread
In all cases, the timer itself will be asynchronous - it won't "take up" a thread until it fires.
Source: Do .NET Timers Run Asynchronously?
I have a timer named SendTimer, the interval is 30 secs.
protected void SendTimer_Tick(object sender, eventArgs e)
{
SendTimer.Enabled = false;
TransferMoney();
System.Threading.Thread.Sleep(15000);
GenerateTransactions();
SendTimer.Enabled = true;
}
I expected tick event to be called correctly by one thread at the same time. NOT by 2 threads simultaneously. but as I saw in my LOGS it seems to be called by a thread while another thread was in action. Any Idea? Because I disable and enable it respectively.
Windows Forms Timer is a single-threaded by definition. It has nothing about multithreading, because it elapses via WM_TIMER message, being sent to current GUI thread message queue.
So, this:
NOT by 2 threads simultaneously
is incorrect, because even if you have several threads, WinForms Timer has nothing to do with this.
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).