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.
Related
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 working with a timeout which is set to occur after a certain elapsed period, after which I would like to get a callback. Right now I am doing this using a Timer that when fired disposes of itself.
public class Timeouter
{
public void CreateTimeout(int timeout, Action onTimeout)
{
Timer t = null;
t = new Timer(_ =>
{
onTimeout();
t.Dispose();
}, new object(), timeout, Timeout.Infinite);
}
}
I'm a bit concerned regarding the resource use of this timer since it could potentially be called quite frequently and would thus setup a lot of timers to fire just once and dispose of themselves. Considering that the timer is an IDisposable it would indicate to me that it indeed uses some sort of expensive resource to accomplish its task.
Am I worrying too much about the resource usage of the Timer, or perhaps the solution is fine as it is?
Do I have any other options for doing this? Would it be better to have a single timer and fiddling with it's frequency starting and stopping it as necessary in order to accommodate several of these timeouts? Any other potentially more lightweight option to have a task execute once after a given period of time has elapsed?
.Net has 2 or 3 timer classes which are expensive. However the System.Threading.Timer class which you're using is a very cheap one. This class do not use kernel resources or put a thread to sleep waiting for timeout. Instead it uses only one thread for all Timer instances, so you can easily have thousands of timers and still get a tiny processor and memory footprint. You must call Dispose only because you must notify the system to stop tracking some timer instance, but this do not implies that this is a expensive class/task at all.
Once the timeout is reached this class will schedule the callback to be executed by a ThreadPool thread, so it do not start a new thread or something like this.
Though its not an answer, but due to length I added it as answer.
In a server/Client environment, AFAIK using Timers on server is not the best approach, rather if you have thick clients or even thin clients, you should devise some polling mechanism on client if it wants a certain operation to be performed on the server for itself(Since a client can potentially disconnect after setting up a timer and then reinstantiate and set a timer again an so on, causing your server to be unavailable at sometime in future(a potential DOS attack)),
or else think of a single timer strategy to deal with all clients, which implements sliding expirations or client specific strategies to deal with it.
one other option is to maintain a sorted list of things which will timeout, add them to the list with their expiry time instead of their duration, keep the list sorted by the expiry time and then just pop the first item off the list when it expires.
You will of course need to most of this on a secondary thread and invoke your callbacks. You don't actaully need to keep the thread spinning either, you could set a wait handle on the add method with a timeout set for (a bit less than) the duration until the next timeout is due. See here for more information on waiting with a timeout.
I don't know if this would be better than creating lots of timers.
Creating a cheap timer that can time many intervals is intuitively simple. You only need one timer. Set it up for the closest due time. When it ticks, fire the callback or event for every timer that was due. Then just repeat, looking again through the list of active timers for the next due time. If a timer changes its interval then just repeat the search again.
Something potentially expensive might happen in the callback. Best way to deal with that is to run that code on a threadpool thread.
That's extraordinarily frugal use of system resources, just one timer and the cheapest possible threads. You pay for that with a little overhead whenever a timer's state changes, O(n) complexity to look through the list of active timers, you can make most of it O(log(n)) with a SortedList. But the Oh is very small.
You can easily write that code yourself.
But you don't have to, System.Timers.Timer already works that way. Don't help.
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
I have a C# program, which has an "Agent" class. The program creates several Agents, and each Agent has a "run()" method, which executes a Task (i.e.: Task.Factory.StartNew()...).
Each Agent performs some calculations, and then needs to wait for all the other Agents to finish their calculations, before proceeding to the next stage (his actions will be based according to the calculations of the others).
In order to make an Agent wait, I have created a CancellationTokenSource (named "tokenSource"), and in order to alert the program that this Agent is going to sleep, I threw an event. Thus, the 2 consecutive commands are:
(1) OnWaitingForAgents(new EventArgs());
(2) tokenSource.Token.WaitHandle.WaitOne();
(The event is caught by an "AgentManager" class, which is a thread in itself, and the 2nd command makes the Agent Task thread sleep until a signal will be received for the Cancellation Token).
Each time the above event is fired, the AgentManager class catches it, and adds +1 to a counter. If the number of the counter equals the number of Agents used in the program, the AgentManager (which holds a reference to all Agents) wakes each one up as follows:
agent.TokenSource.Cancel();
Now we reach my problem: The 1st command is executed asynchronously by an Agent, then due to a context switch between threads, the AgentManager seems to catch the event, and goes on to wake up all the Agents. BUT - the current Agent has not even reached the 2nd command yet !
Thus, the Agent is receiving a "wake up" signal, and only then does he go to sleep, which means he gets stuck sleeping with no one to wake him up!
Is there a way to "atomize" the 2 consecutive methods together, so no context switch will happen, thus forcing the Agent to go to sleep before the AgentManager has the chance to wake him up?
The low-level technique that you are asking about is thread synchronisation. What you have there is a critical section (or part of one), and you need to protect access to it. I'm surprised that you've learned about multithreaded programming without having learned about thread synchronisation and critical sections yet! It's essential to know about these things for any kind of "low-level" multithreaded programming.
Maybe look into Parallel.Invoke or Parallel.For in .NET 4, which allows you to execute methods in parallel and wait until all parallel methods have been invoked.
http://msdn.microsoft.com/en-us/library/dd992634.aspx
Seems like that would help you out a lot, and take care of all the queuing for you.
humm... I don't think it's good idea (or even possible) develop software in .NET worrying about context switches, since neither Windows or .NET are real time. Probably you have another kind of problem in that code.
I've understood that you simply run all your agents in parallel, and you want to wait till all of them have finished to go to the next stage. You can use several techniques to accomplish that, the easiest one would be using Monitor.Wait(Object monitor) and Monitor.PulseAll(Object monitor).
In the task library there are several things to do it as well. As #jishi has pointed out, you can use the Parallel flavours, or spawn a lot of Tasks and then wait for all with the Task.WaitAll(Task[] tasks) method.
Each time the above event is fired,
the AgentManager class catches it, and
adds +1 to a counter.
How are you adding 1 to that counter and how are you reading it? You should use Interloked.Increment to ensure an atomic operation, and read it in a volatile operation with Thread.VolatileRead for example, or simply put it in a lock statement.
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.