System.Threading.Timer callback is never called - c#

My System.Threading.Timer (which has a callback) never fires reliably. This is part of my programming assignment where I input the amount of time the timer is supposed to run from a textbox.
The timer is declared like this:
System.Threading.Timer timer = new System.Threading.Timer(WorkerObject.callback, null, delay, Timeout.Infinite);
And the delay is the simply an int describing the delay for the callback to fire the first time (it is only supposed to fire once).
The callback method is like this:
public static void callback(Object stateinfo)
{
stop = true;
}
And all that does is set a flag to true which stops a loop (which is being run by a thread on a ThreadPool, in effect, stopping the thread).
The loop looks like this:
while (!stop)
{
currentTextbox.Invoke(new Action(delegate()
{
currentTextbox.AppendText((counter++) + Environment.NewLine);
currentTextbox.Update();
}));
}
My problem is that the stop variable is always false for any delay over 5000 milliseconds. Is there a way to "force" the callback to always fire?

You need to hold on to the reference to the timer.
Most likely the timer object is being garbage collected, which will run its finalizer, stopping the timer.
So hold on to the reference for as long as you need the timer to be alive.

I would suggest using a CancellationTokenSource:
static CancellationTokenSource Cancel = new CancellationTokenSource();
public static void Callback(object state)
{
Cancel.Cancel();
}
and your loop:
while (!Cancel.IsCancellationRequested)
{
...
}
This is much cleaner than using volatile, and is easier to port when you move your simple proof of concept to separate classes. See my blog, Polling for Cancellation, for more info.

The runtime Jitter is probably optimizing away your while(!stop) condition to while(true).
Mark the stop variable as volatile.
private volatile bool stop = false;

Related

How to create an application loop in C#

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.

Scheduled operations in C# with option to FullStop immediately

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.

What is the expected behavior of a locally scoped Timer?

Specifically, if you create an instance of a Timer in the local scope, and then return from that scope:
1) Will the timer still execute?
2) When would it be garbage collected?
I offer these two scenarios:
Timer timer = new Timer(new TimerCallback((state) => { doSomething(); }));
timer.Change((int)TimeSpan.FromSeconds(30), (int)TimeSpan.FromSeconds(30));
return;
And
Timer timer = new Timer(new TimerCallback((state) => { doSomething(); }));
timer.Change((int)TimeSpan.FromSeconds(30), Timeout.Infinite);
return;
The TimerCallback has a reference to the method DoSomething(), and therefore (in your example) to this but there is no live reference going the other way so it should get collected...eventually
The timer might or might not execute, depends on whether garbage collection runs before the time executes. This is why it's good practice to keep a reference to the timer somewhere other than on the stack.
Note that this is not always problematic; for example, threads won't be collected as long as they are still running.
Here's a quick test:
class Program
{
static void Main(string[] args)
{
Something something = new Something();
Foo(something);
Console.ReadKey(true);
GC.Collect();
Console.ReadKey(true);
}
private static void Foo(Something something)
{
Timer timer = new Timer(new TimerCallback(something.DoIt),null,0,5);
return;
}
}
public class Something
{
public void DoIt(object state)
{
Console.WriteLine("foo{0}", DateTime.Now.Ticks);
}
}
This is essentially what the compiler blows it out to (the Lambda expression in your example). When you run this, you'll notice that as long as you don't hit the first key, it'll keep putting stuff out to the console. As soon as you hit a key, and the GC kicks in, it stops. Timer still has a reference to Something, but nothing has a reference to Timer, so it's gone.
If you're talking about System.Threading.Timer, it implements IDisposable, so you should maintain a reference to it so that you can call Dispose when you're no longer using it. I don't know the answer to your particular question, but you can investigate it in a console application by running many iterations and forcing GC.Collect() to see if the Timer continues to fire. My guess is that it will eventually be collected and stop firing, unless there is some statically rooted reference created internally.
On a side note, if you want a one-time Fire-and-forget timer, you can implement one by creating a state object with a reference to the Timer, so it can Dispose itself when the timer event fires. I have a TimerService class with a WhenElapsed(TimeSpan, Action) method that uses this pattern and it's very handy for creating timeouts without having to manage the Timer instance as a field in the containing class.

Synchronizing a Timers.Timer elapsed method when stopping

With reference to this quote from MSDN about the System.Timers.Timer:
The Timer.Elapsed event is raised on a
ThreadPool thread, so the
event-handling method might run on one
thread at the same time that a call to
the Timer.Stop method runs on another
thread. This might result in the
Elapsed event being raised after the
Stop method is called. This race
condition cannot be prevented simply
by comparing the SignalTime property
with the time when the Stop method is
called, because the event-handling
method might already be executing when
the Stop method is called, or might
begin executing between the moment
when the Stop method is called and the
moment when the stop time is saved. If
it is critical to prevent the thread
that calls the Stop method from
proceeding while the event-handling
method is still executing, use a more
robust synchronization mechanism such
as the Monitor class or the
CompareExchange method. Code that uses
the CompareExchange method can be
found in the example for the
Timer.Stop method.
Can anyone give an example of a "robust synchronization mechanism such as the Monitor class" to explain what this means exactly?
I am thinking it means use a lock somehow, but I am unsure how you would implement that.
Stopping a System.Timers.Timer reliably is indeed a major effort. The most serious problem is that the threadpool threads that it uses to call the Elapsed event can back up due to the threadpool scheduler algorithm. Having a couple of backed-up calls isn't unusual, having hundreds is technically possible.
You'll need two synchronizations, one to ensure you stop the timer only when no Elapsed event handler is running, another to ensure that these backed-up TP threads don't do any harm. Like this:
System.Timers.Timer timer = new System.Timers.Timer();
object locker = new object();
ManualResetEvent timerDead = new ManualResetEvent(false);
private void Timer_Elapsed(object sender, ElapsedEventArgs e) {
lock (locker) {
if (timerDead.WaitOne(0)) return;
// etc...
}
}
private void StopTimer() {
lock (locker) {
timerDead.Set();
timer.Stop();
}
}
Consider setting the AutoReset property to false. That's brittle another way, the Elapsed event gets called from an internal .NET method that catches Exception. Very nasty, your timer code stops running without any diagnostic at all. I don't know the history, but there must have been another team at MSFT that huffed and puffed at this mess and wrote System.Threading.Timer. Highly recommended.
That is what it is suggesting.
Monitor is the class that's used by the C# compiler for a lock statement.
That being said, the above is only a problem if it is an issue in your situation. The entire statement basically translates to "You could get a timer event that happens right after you call Stop(). If this is a problem, you'll need to deal with it." Depending on what your timer is doing, it may be an issue, or it may not.
If it's a problem, the Timer.Stop page shows a robust way (using Interlocked.CompareExchange) to handle this. Just copy the code from the sample and modify as necessary.
Try:
lock(timer) {
timer.Stop();
}
Here is a very simple way to prevent this race condition from occurring:
private object _lock = new object();
private Timer _timer; // init somewhere else
public void StopTheTimer()
{
lock (_lock)
{
_timer.Stop();
}
}
void elapsed(...)
{
lock (_lock)
{
if (_timer.Enabled) // prevent event after Stop() is called
{
// do whatever you do in the timer event
}
}
}
Seems timer is not thread safe. You must keep all calls to it in sync via locking. lock(object){} is actually just short hand for a simple monitor call.

Why System.Timer doesn't change class member variable?

I have a while loop and in this loop, there is a if condition.
But condition will be changed by a timer. But timer never change global variable.
I cant understand.
Where is the problem?
Example:
bool enterHere = false;
Timer timer = new Timer(); //Timer Started
private void timer_Tick(object Sender, ...)
{
enterHere = true;
}
private void function()
{
while(...)
{
if(enterHere)
{
//Never enter here
}
}
}
As another lesson in why you should always post your real code when asking questions on SO...
It appears the solution to your problem is quite a bit simpler than the other answers suggest. The timer's Tick event is never going to be raised, thus the value of the enterHere variable is never going to be changed, because you never actually start the timer. More specifically, this line is incorrect:
Timer timer = new Timer(); //Timer Started
The constructor does not start the timer; you need to call its Start method. This is confirmed by the documentation, which says:
When a new timer is created, it is disabled; that is, Enabled is set to false. To enable the timer, call the Start method or set Enabled to true.
Absolutely no reason to muck about with things like Application.DoEvents if you don't have to.
I assume you're using a System.Windows.Forms.Timer in which case the Tick event will run on the same thread as your function(). You can put
Application.DoEvents();
Inside your loop to get the timer to tick. Alternatively you could use an other timer (such as the System.Threading one), which executes on a different thread.
What else are you doing in the WHILE(...) loop and have you checked the processor usage when your code is running? If the loop is running very quickly there is no time for your app to process it's messages and react to the timer message.
As deltreme says, inserting Application.DoEvents(); in the loop should give it a chance to process the message.
Ideally the timer should be running in a different thread if you have a loop like that. The timer will never be able to raise the event.
Alteratively you could call DoEvents() to allow the timer to do it's work

Categories