For some time now I've been having this recurrent nightmare (read - bug in my application). For some reason, a certain Timer continues to send "Elapsed" events after I stopped it, even though in the event itself the timer "admits" to having been disabled! Check this out:
//Timer is created in Class' Constructor. Class is not static.
public PDAAccess ()
{
ConnectionTimeoutChecker = new System.Timers.Timer(1000);
ConnectionTimeoutChecker.Elapsed += new System.Timers.ElapsedEventHandler(ConnectionTimeoutChecker_Elapsed);
}
void ConnectionTimeoutChecker_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{ //_DeviceConTimeout eventually reaches A LOT MORE than 10.
if (_DeviceConTimeout > 10)
{
ConnectionTimeoutChecker.Stop(); //This is invoked but the timer DOES NOT STOP.
if (OnDeviceSyncTimeout != null) OnDeviceSyncTimeout(this, null); //This gets fired all the time.
}
_DeviceConTimeout++; //This keeps increasing and increasing.
//Worth mentioning: sender = Timer, sender.Enabled = false (!) so then why is this executing?
}
As for where I start it: I start it in a single place, I put a breakpoint there and it doesn't execute more than once. And before you ask: no multiple threads are involved. I do work with threads in this application, but: the timer is not created in a thread, neither is the Class.
Yet the .Stop(); is executed 100 times and the timer still WON'T stop.
I'm completely at a loss here. This behavior is so strange to me, it gives me that embarrassed feeling that I might have been missing something super-obvious. Sometimes writing such a post helps me identify the problem before I hit the submit button (we all know the "Explaining to 3rd party" effect). But it didn't hit me yet so I'm gonna hit the button and... see what you see ::- D.
Shot in the dark: Perhaps the call to OnDeviceSyncTimeout() somehow indirectly causes the timer to be reactivated? I know you said it is started only in a single place, but I’m not really sure how you can be so certain about that.
Well, that doesn't make much sense with the code snippets you posted. But extraordinary problems like this require extraordinary explanations.
The System.Timers.Timer class is a horrid timer. The condition you see, getting the Elapsed event called while the timer is stopped, is inevitable in most any use for it. The problem is that it raises the Elapsed event by using ThreadPool.QueueUserWorkItem(). That thread is subject to the vagaries of the thread pool scheduler and the Windows thread scheduler. QUWI does not guarantee that the thread will run right away. Instead, the thread goes in a queue in the "ready to run" state. The TP scheduler removes it from that queue only when it deems the time right to run a thread. Which for one means that it will be stuck for a while if it already has as many threads running as your machine has CPU cores. Only when threads don't complete will it allow more threads to run. That takes a while, these scheduling decisions only run twice a second.
The Windows thread scheduler plays a role as well. When the machine is loaded, having many threads ready to run then it can take a while before the Elapsed thread gets a turn. What is especially nasty about this problem is that such a race is heavily dependent on what else is going on in your program or on the machine. Runs fine on your dev machine, malfunctions unpredictably in production when the Elapsed event finally manages to run, even though the timer got stopped a long time ago.
Also note that this can build up. You are particularly vulnerable to that because you stop the timer in the Elapsed event. When the TP threads just don't manage to get scheduled, the timer just keeps calling QUWI, addding more TP threads, without your code able to stop the timer.
Well, guesses, but it does explain the problem. Either the synchronous timer in your UI library or System.Thread.Timer should fix it. Do try to use the single-shot version of the latter. A time-out is a fixed time, it shouldn't have to be counted.
Related
Ok I am sure I am not using the state machine correctly but here is subset of sample code. This is the Appccelerate.StateMachine which used to be bbvcommon.StateMachine.
fsm.In(State.Idle)
.ExecuteOnEntry(() => {
// wake up and check if there are people still standing and if so restart
if(currentlyTalkingTo.Count() > 0)
{
fsm.Fire(Event.PersonFound);
}
})
.On(Event.PersonFound).Goto(State.WaitToRecognizePeople);
fsm.In(State.WaitToRecognizePeople)
.ExecuteOnEntry(() => {
Thread.Sleep(1000);
fsm.Fire(Event.TimeOut);
})
.On(Event.TimeOut).Goto(State.Greet);
The issue is what the best way to handle a sleep? With this code calling fsm.Stop() when shutting the application down sometimes hangs the application. Commenting all the Thread.Sleeps() in the states fixes the issue so the application successfully shuts down.
What is the recommended way of handling states that need to time out and move to another state? Sample code would be appreciated.
The Thread.Sleep would block the state machine, both the PassiveStateMachine and ActiveStateMachine, so that you cannot react to other events anymore during the sleep time. That might be an explanation for why a call to Stop sometimes hangs the explanation.
I assume you don't just want to wait for a given period of time but want to wait for some event under a timeout condition. I would then recommend to start a Timer in the ExecuteOnEntry of WaitToRecognizePeople that, when elapsed, fires the event Event.Timeout.
If you have many states that have associated timeouts, to avoid a lot of duplicated code, you could even implement this in a separate class as a state machine extension, like I did in one of my projects using this library. (see http://www.appccelerate.com/statemachineextensions.html).
I'm currently writing something in C# (which I've never really used before) that involves a single timer System.Timers.Timer firing 7 queries run against an Oracle Database. It's designed to be running continuously and indefinitely on a server.
When looking at the process running in the Windows Resource Monitor, the thread count was just increasing. At an interval of 10 seconds, it had reached 230 threads in under an hour. I guess that every time the timer fires, it creates a new thread but I can't really work out what's wrong. I assumed that I wouldn't have to explicitly end the thread after the task had been completed.
However, when I added a Thread.CurrentThread.Abort()after the last query had finished doing work, the thread count stays at 15. Also, memory usage is quite a lot better too.
Is aborting the thread the right thing to do? It feels very wrong but it has fixed the problem.
Using Thread.Abort() is of course not a proper fix, just a band-aid that hides the true problem. You must find out why these threads don't stop running by themselves.
Do so by using the debugger. Debug + Windows + Threads show these threads. Select one that looks like a timer callback thread and look at its call stack so see where it got stuck. Best done by also enabling unmanaged debugging and enabling the Microsoft symbol server so you can also see it being stuck in code you didn't write. The name of a DLL you find back in the call stack is usually a hint.
See the remarks on http://msdn.microsoft.com/en-us/library/0tcs6ww8.aspx
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.
Basically this looks like your query does either not finish in the given time or it locks the thread on which it is running.
I'm developing an app that starts a System.Threading.Timer which does some fairly rapid reading/writing to the serial port (every 100ms). The timer's callback method looks something like this:-
if (_timerTaskRunning)
{
Debug.WriteLine("still running");
return;
}
_timerTaskRunning = true;
... do the serial write/read here ...
_timerTaskRunning = false;
The _timerTaskRunning flag is a safeguard to ensure that the delegate doesn't run if the previous timer "cycle" hasn't finished, i.e. it's taking longer than 100ms.
When I first start the app I see around a dozen debug messages from the if statement. It'll then settle down but I see another group of messages 7 or 8 seconds later. It settles down again, and every once in a while I'll see a group of messages appear in varying numbers.
I'm assuming the first group of messages are caused by the timer delegate running slowly due to the app still starting up, objects/UI initialising, etc, etc, while subsequent messages are perhaps caused by garbage collection kicking in every so often and slowing things down? It's not the serial port because I see the same behaviour with a "mock" serial port.
I've tried delaying the timer's first run by a couple of seconds but it makes no difference - I still get a batch of debug messages for the first second or so after the timer starts. It's not the end of the world skipping some of the timer tasks but it would be interesting to know what might be causing them. Is there anything I can do to investigate the cause further, e.g. would perfmon shed any light on things? I haven't used it before so which counters would you suggest?
It sounds like you have a reentrancy problem. Basically your _timerTaskRunning isn't working as a safeguard likely due to race conditions.
Use System.Timers.Timer instead of System.Threading.Timer
Set Timer.AutoReset to false. This will fix your entrancing problem because it won't call you call back until you explicitly want it to.
Call Start() on your timer when you need it to go again (you may need to adjust the interval to account for execution time)
If you have multiple threads that can call start you will need to synchronize the calls to it.
Your _timerTaskRunning gets updated by several threads. You need to use locking to make it thread-safe.
However, I would not use a timer at all. I have implemented a non-renetrant timer here. It uses AutoResetEvent WaitOne with timeout which ensures non-reentry.
I'm new in C# and I'm using System.Threading.
I have this code:
UISystem.SetScene(Scene_Menu);
Thread.Sleep (9000);
p.Text="HELLO";
Thread.Sleep(9000);
p.Text="WORLD";
It delays 18 seconds, but the p.Text="HELLO" doesn't show between the sleep functions. What's the problem with my code?
Thanks.
Timers don't work since I can't edit p from a separate thread.
Application.DoEvents() is a Windows Forms function, I'm building an application in PS Vita.
You have discovered why you should never use Thread.Sleep. It is useful for only two things. (1) Writing test cases that need to simulate a thread being busy for a certain number of seconds, and (2) Sleeping for zero milliseconds tells the operating system "I cede the rest of my time slice to another process if there exists one that wants it"; it's a politeness thing.
You should never use thread.Sleep to introduce a delay as you are doing for exactly the reason you have discovered. You are setting a property, but setting a property does not cause the operating system to repaint the screen. Consider if it did; you might have a thousand property sets in a method, and you would have to repaint the screen after all of them, which would look ugly and be very slow.
Instead what happens is the property is set and the object makes a note to the operating system that says when this thread is available to handle operating system messages again, please repaint me. Your program is, instead of telling the operating system "I'm done, go ahead and see if there are any message for me" that instead you want the thread to do nothing for nine seconds.
Now, you can tell the program to check for messages by calling DoEvents but using DoEvents is also a bad idea and you should not do it. Doing so essentially causes your program to exhibit symptoms of Attention Deficit Disorder; you have not finished the current job and you are looking to see if there are new jobs to do without removing the old jobs from the call stack! Suppose those new jobs in turn get interrupted, and so on, and so on. The stack grows without bound, which is very bad. DoEvents is a "worst practice", just like sleeping a thread. You can get away with it in small simple programs but it leads to big trouble when the program becomes complex.
Moreover: yes, DoEvents will paint your control, but that is all it will do. For the next nine seconds, the application will appear to the user to be completely hung. That is a very bad user experience.
The right thing to do if you want to introduce a delay is to asynchronously wait. In C# 4 and earlier the standard way to do that is to create a timer, and when the timer ticks, do the next thing.
Now, you say that you cannot use a timer because you need to access the control from the UI thread. That's fine. The timer's tick event handler will run on the UI thread, not on a separate thread. You can safely use a timer.
In C# 5, the right thing to do is to use the new await keyword to introduce an asynchronous wait. That is, a wait that does other stuff while it is waiting, instead of going to sleep while it is waiting. In C# 5 you would write your code as:
UISystem.SetScene(Scene_Menu);
await Task.Delay (9000);
p.Text="HELLO";
await Task.Delay(9000);
p.Text="WORLD";
C# 5 is at present in beta; for details on this new feature see:
http://msdn.microsoft.com/en-us/async
For a gentle introduction to async and an explanation of why DoEvents is bad news, see my MSDN magazine article:
http://msdn.microsoft.com/en-us/magazine/hh456401.aspx
Background is the following: A Windows Service which is supposed to perform an action once per day at a given time.
I have currently implemented this by creating a timer and added the ElapsedEventHandler. The event fires every t minutes and it is then checked that we are passed the configured time. If so the action is performed and if not nothing happens.
A colleague asked me if it was not easier just to have a while(true) loop containing a sleep() and then of course the same logic for checking if we are past the time for action.
Question:
Can one say anything about the "robustness" of an event vs. a while(loop)? I am thinking of the situation where the thread "dies" so the while(true) loop exits. Is this more "likely" to happen in the one scenario vs. the other?
I'd vote for neither.
If your service just sits idle for an entire day periodically waking up (and paging code in) to see if "it's time to run", then this is a task better suited for the Windows Task Scheduler. You can programatically install a task to run every day through the task scheduler. Then your code doesn't need to be running at all unless it's time to run. (Or if your service does need to run in the background anyway, the task in the scheduler can signal your service to wake up instead of timer logic).
Both will be equally robust if you use proper error handling.
If you don't use proper error handling they will be equally brittle.
while(true)
{
...
Thread.Sleep(1000);
}
will make your service slow when responding to the standard service events like OnStop.
Besides, where do you put your while loop? In a separate thread? You will get more manual management if you use a loop too.
To summarize: use a timer.