I have the following scenarios using System.Timers.Timer.
Create a Timer object and assign the method
_JobListener.Enabled = false;
_JobListener.Elapsed += (this.JobListener_Elapsed);
Within JobListener_Elapsed, I created another thread to run some functions.
JobListener_Elapsed
{
//stop the timer
_JobListener.Enabled = false;
System.Threading.Thread pollThread = new Thread(JobListener_ElapsedAsync);
pollThread.Start();
//join to the main timer thread
pollThread.Join();
//restart the timer
_JobListener.Enabled = true;
}
Within JobListener_ElapsedAsync, I log the timer Enabled status.
private void JobListener_ElapsedAsync()
{
try{
log Timer.Enabled
some other code
}finally
{
_JobListener.Enabled = true;
}
}
However, I can see some times, it can see the timer status to be true, which is wrong. The timer should be stopped when JobListener_ElapsedAsync is running.
Any idea?
There are two main classes of timer in the .NET Framework: thread timers, and window timers.
System.Threading.Timer is the basic class for thread timers. This wraps the Windows waitable timer object. The Tick event is fired on the ThreadPool. It does not check whether all handlers for a previous Tick have returned before firing Tick again. The timer should fire on time - it is not delayed.
System.Windows.Forms.Timer wraps the Windows SetTimer API. The Tick event is fired on the thread that creates the timer. If that isn't a UI thread it won't actually fire. Timers are the lowest priority messages; they are only generated by GetMessage/PeekMessage when no other messages are outstanding. Therefore they can be delayed significantly from when they should be generated.
System.Timers.Timer wraps System.Threading.Timer. If you have set its SynchronizingObject property to something, when the underlying timer fires, it will use ISynchronizeInvoke.Invoke to get onto that object's thread (analogous to Control.Invoke - indeed Control implements ISynchronizeInvoke). It blocks the thread pool thread in the process. If SynchronizingObject is null it just fires the Elapsed event on the thread pool thread. The only real use for this class is if you need timers for UI components to be fired on time. If you don't need to synchronize, use a System.Threading.Timer instead.
If you need to ensure that a previous Tick event is fully handled (all handlers have returned) before the next one is started, you need to either:
Make the timer one-shot rather than periodic, and have the last handler set up another shot when it finishes executing
Use a lock or Monitor to prevent two threads entering the handler (but you could use up all threads in the thread pool)
Use Monitor.TryEnter to only enter the handler if the previous one has finished (but you could miss some Ticks).
Related
I am facing a issue when used to system.timers.time, i have a running process in my application.
with timer called my process start, but i want to use that process within the thread only.
because every time timer elapsed event called the new thread has been generated, but i want to prevent this and only using single thread in a process.
Here is my code.
Public void Watcher()
{
System.Timers.Timer timer = new System.Timers.Timer();
timer.Interval = 3000;
timer.Elapsed += OnTimedEvent;
timer.Enabled = true;
}
Public void OnTimedEvent
{
// process code here
}
Here, after every 3 seconds OnTimedEvent called and new thread created, but i don't want to create new thread every time.
So, how to prevent this, any idea?
If you have a UI you should simply use forms timer or dispatch timer. If you do not have a UI you can set the SynchronizationObject of the timer. This will be responsible for marshaling the execution to the right thread.
I would probably skip the synchronization object, and just do the marshaling in the event handler of the event.
In either case you will need some kind of message loop if you do not have a UI. This would have a threadsafe queue where the thread takes a message and process it, one at a time. For example, using a blocking collection of Action.
As mentioned by #MindSwipe in the comments. A new thread will not be generated per event. It will simply take threads from the threadpool. So the number of threads used should be fairly constant. The main reason for moving all execution to one thread is because it can make threadsafety easier to manage.
I have a console server in C# that keeps running in a while(true) loop. But that takes > 50% CPU even if it is doing nothing. I tried Thread.Sleep it worked! Not eating my CPU anymore but, it do not resumes in the exact time specified and is not considered good practice. Am I doing the right thing? Or is there any other way than using while(true) and Thread.Sleep?
When you want to suspend thread for a while without consuming CPU resources, you usually use some WaitHandle (such as AutoResetEvent or ManualResetEvent) and call it's WaitOne() method to suspend thread until event that is supposed to wake it up occurs (e.g. key is pressed, new network connection arrives, asynchronous operation finishes, etc.).
To wake up thread periodically, you can use timer. I'm not aware of any timer in .NET Framework, that provides WaitHandle (of course you can easily create such class yourself), so have to use Timer and call AutoResetEvent.Set() manually on each tick in it's callback.
private static AutoResetEvent TimerWaitHandle = new AutoResetEvent(false);
static void Main()
{
// Initialize timer
var timerPeriod = TimeSpan.FromMilliseconds(500);
Timer timer = new Timer(TimerCallback, null, timerPeriod, timerPeriod);
while(true)
{
// Here perform your game logic
// Suspend main thread until next timer's tick
TimerWaitHandle.WaitOne();
// It is sometimes useful to wake up thread by more than event,
// for example when new user connects etc. WaitHandle.WaitAny()
// allows you to wake up thread by any event, whichever occurs first.
//WaitHandle.WaitAny(new[] { TimerWaitHandle, tcpListener.BeginAcceptSocket(...).AsyncWaitHandle });
}
}
static void TimerCallback(Object state)
{
// If possible, you can perform desired game logic here, but if you
// need to handle it on main thread, wake it using TimerWaitHandle.Set()
TimerWaitHandle.Set();
}
I can't comment, so i'll put it here.
Theorically with Thread.sleep(1) it won't use that much CPU.
You can get more info from this question/answer: What is the impact of Thread.Sleep(1) in C#?
You can use System.Threading.Timer class. It Provides a mechanism for executing a method on a thread pool thread at specified intervals.
Example
public void Start()
{
}
int dueTime = 1000;
int periodTS = 5000;
System.Threading.Timer myTimer = new System.Threading.Timer(new TimerCallback(Start), null, dueTime, periodTS);
This will call start method after 1 second from calling it and after that start will be called after every 5 second.
You can read more about Timer class here.
I need to set up a simple elapsed Timer in C# (MonoBehavior) that calls a method when complete, but can also be cancelled before finishing. If cancelled or stopped, it automatically resets its interval. I don't need anything fancy like threading.
Reading over the documentation on C# Timers https://msdn.microsoft.com/en-us/library/System.Timers.Timer%28v=vs.110%29.aspxstill a bit confused. For instance, when you set mytimer.Enabled=false does it also reset the timer back to 0? Perhaps I should be looking at Coroutines instead?(this is for Unity)
In AS3 I would do something like this
private var _delayTimer:Timer;
//create a Timer object that runs once for 1 second
_delayTimer = new Timer(1000,1);
//add handler
_delayTimer.addEventListener(TimerEvent.COMPLETE, onDelay);
//start timer
_delayTimer.start();
private function onDelay(e:TimerEvent):void{
trace('delay finished!);
}
//some other method to interrupt-stop and reset the delay timer
private function foo():void{
_delayTimer.reset();
}
By using System.Timers.Timer, you are using multi-threading - it's quite likely this is not what you want.
Instead, you probably want System.Windows.Forms.Timer - this will post the timer event back on the UI thread (if you're using Windows Forms, of course).
You can use Start and Stop the way you want, because there's actually no ticking clock - it just registers a callback from Windows in the future, basically.
Relevant piece of documentation from MSDN:
Calling Start after you have disabled a Timer by calling Stop will cause the Timer to restart the interrupted interval. If your Timer is set for a 5000-millisecond interval, and you call Stop at around 3000 milliseconds, calling Start will cause the Timer to wait 5000 milliseconds before raising the Tick event.
I need to do some operations on a certain interval (e.g. from 5 to 5 minutes in a loop) but need to be able to fully stop the thing whenever I want (on push of a button).
I was thinking into using a Timer class but events might fire even after the timer is stopped.
How can I have some code running on a timer and still be able to immediately bring everything to a complete stop?
Just so I am properly understood: By complete stop I mean that events stop and I can dispose of objects like the timer itself etc. I am not asking how to avoid having side effects from unexpected events that are fired after the timer is stopped!
Answer to this question depends a lot on a type of your operations.
Best scenario is to run a thread with a loop and listen to abort event.
static AutoResetEvent abort = new AutoResetEvent();
Thread worker = new Thread(WorkerThread);
void MainThread()
{
worker.Start();
Thread.Sleep(30000);
abort.Set();
}
void WorkerThread()
{
while(true)
{
if(abort.WaitOne(5000)) return;
// DO YOUR JOB
}
}
When you call abort.Set() from another thread, this one will exit.
But if your code is long running, you won't be able to exit until job is done.
To exit immediately you will have to abort thread, but this is not too wise because of resource consumption.
Alternatively, if your operation is long running (let's say you are going through long array), you can check "abort" event state from time to time (every iteration of loop, for example) like this abort.WaitOne(0).
The race condition with the timer is unavoidable since, as you say, the callbacks are executed from the thread pool. However, I believe you can safely dispose the timer even while it's still executing the events. An option which might help is if you consider using the System.Threading.Timer instead of System.Timers.Timer, for which you can call Timer.Dispose(WaitHandle) if you need to have a way to know when the timer events have finished executing. This will prevent race conditions for the cases where you also need to dispose of some other resource - a resource that the event consumer function will attempt to use.
As for the "immediate" requirement, the most immediate would probably be something that uses a synchronization primitive of sorts to stop execution. For example consider this:
static System.Timers.Timer timer;
static void Main(string[] args)
{
var cancelSource = new CancellationTokenSource();
timer = new System.Timers.Timer(200);
timer.Elapsed += new SomeTimerConsumer(cancelSource.Token).timer_Elapsed;
timer.Start();
// Let it run for a while
Thread.Sleep(5000);
// Stop "immediately"
cancelSource.Cancel(); // Tell running events to finish ASAP
lock (timer)
timer.Dispose();
}
class SomeTimerConsumer
{
private CancellationToken cancelTimer;
public SomeTimerConsumer(CancellationToken cancelTimer)
{
this.cancelTimer = cancelTimer;
}
public void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
lock (timer)
{
// Do some potentially long operation, that respects cancellation requests
if (cancelTimer.IsCancellationRequested)
return;
// More stuff here
}
}
}
This is a toy example, but it illustrates my point. The 3 lines that do the "stop immediately" have the following features:
By the time the Dispose call returns, none of the // More stuff here code will ever execute again.
None of the // More stuff here code can execute while the timer is being disposed, because of the lock.
The previous 2 features require the lock, but they prevent the timer from stopping "immediately" because on entering the lock it needs to wait for all timer events calls to finish if they have started. For this reason I added in the cancellation as the fastest way to abort the currently executing events while still guaranteeing that they won't be executing during timer dispose.
Note: if you need multiple timer events to execute simultaneously, consider using a ReaderWriterLockSlim instead of a monitor.
I'd consider one of these two options:
Put a safety check in the events that you need to execute. Something like a database flag. So even if the Timer fails to stop the event will bail out when the safety check fails.
Use something like Quartz.Net for scheduling. This is really heavy handed but it'll do what you want.
I am using System.Timers in my program.
As we know each interval new thread is created to handle the OnTimedEvent.
I am looking for way to force the system to wait creating a new thread if the previous thread is still running.
My OnTimedEvent execute some method and I would like to wait until the method is finished
Any idea how to do that?
You are mistaken in the sense that no new thread will be created when the Elapsed event is fired. The event will be raised on the the .NET threadpool, so an arbitrary thread will process it.
One way to do what you want is to Stop the timer at the start of your event handler and to Start it again once it is finished. Like this:
var timer = new System.Timers.Timer(1000);
timer.Elapsed += HandleTimerElapsed;
timer.Start();
...
private void HandleTimerElapsed(object s, ElapsedEventArgs e)
{
var t = (System.Timers.Timer)s;
t.Stop();
try {
... do some processing
}
finally { // make sure to enable timer again
t.Start();
}
}
The other option is to set the AutoReset property of the timer to false. This way the timer will only be raised once. Then you can call Start when you want it to start again. So the above code would change to include a timer.AutoReset = false; at the beginning and then you don't need to call Stop inside the handler. This is a bit safer as the above method probably has a race condition in the sense that if the system is under load your handler might not be guaranteed to execute before the timer elapses again.