I am developing a Windows Service application, in .NET, which executes many functions (it is a WCF service host), and one of the targets is running scheduled tasks.
I chose to create a System.Threading.Timer for every operation, with a dueTime set to the next execution and no period to avoid reentrancy.
Every time the operation ends, it changes the dueTime to match the next scheduled execution.
Most of the operations are scheduled to run every minute, not all toghether but delayed by some seconds each other.
Now, after adding a number of operations, about 30, it seems that the timers start to be inaccurate, starting the operations many seconds late, or even minutes late.
I am running the operation logic directly in the callback method of the timer, so the running thread should be the same as the timer.
Should I create a Task to run the operation instead of running it in the callback method to improve accuracy?
Or should I use a single timer with a fixed (1 second) dueTime to check which operations need to be started?
I don't like this last option because it would be more difficult to handle reentrancy..
Timers fire on a thread pool thread, so you are probably finding that as you add lots of timers that you are exhausting the thread pool.
You could increase the size of the thread pool, or alternatively ensure you have fewer timers than the thread pool size.
Firing off Tasks from the callback likely won't help - since you are going to be fighting for threads from the same thread pool. Unless you use long-running tasks.
We usually setup multiple timers to handle different actions within a single service. We set the intervals and start, stop the timer on the Service Start/Stop/Shutdown events (and have a variable indicating the status for each one, i.e. bool Stopped)
When the timer ticks over, we stop the timer, run the processing (which may take a while depending on the process, i.e. may take longer than the interval if its short.. (this code needs to be in a try--catch so it keeps going on errors)
After the code has processed, we check the Stopped variable and if its not stopped we start the timer again (this handles the reentrancy that you've mentioned and allows the code to stick to the interval as much as possible)
Timers are generally more accurate after about 100ms as far as I know, but should be close enough for what you want to do.
We have run this concept for years, and it hasn't let us down.
If you running these tasks as a sub-system of an ASP.NET app, you should also look at HangFire, which can handle background processing, eliminating the need for the windows service.
How accurate do the timers need to be? you could always use a single timer and run multiple processing threads at the same time? or queue the calls to some operations if less critical.
Ok, I came to a decision: since I am not able to easily reproduce the behavior, I chose to solve the root problem and use the Service process to only:
serve WCF requests done by clients
schedule operations (which was problematic)
Every operation that could eat CPU is executed by another process, which is controlled directly by the main process (with System.Diagnostics.Process and its events) and communicates with it through WCF.
When I start the secondary process, I pass to it the PID of the main process through command line. If the latter gets killed, the Process.Exited event fires, and I can close the child process too.
This way the main service usually doesn't use much CPU time, and is free to schedule happily without delays.
Thanks to all who gave me some advices!
Related
I am working on .net windows application.
I am using System.Threading.Thread.
In a single form using five(5) threads. I have a code which when run, it executes series of lines in sequence. I would like to add a pause in between.
For that i am using
Thread.Sleep(10800000)
of 3 hours
But I checked in debug mode, after executing line of
Thread.Sleep(10800000)
My debug not goes to next line or next line never executes even after waiting for 4 hours.
I am using this Thread.Delay in other thread not in main thread.
This delay requires because, i send a command to configure setting to a hardware, that setting requires minimum 3 hours to complete.
That's why i am using this
Thread.Delay(10800000)
Means my onward code is proceed only after waiting for 3 hours.
Can any one help me?
Thread.Sleep is not designed for long sleeps. You should consider using somthing like System.Threading.Timer.
Provides a mechanism for executing a method on a thread pool thread at specified intervals.
You can give it a first run time of midnight, and have it go off every 24 hours. the Timer(TimerCallback, Object, TimeSpan, TimeSpan) constructor is exactly what you are looking for.
One would argue that even using a timer is not the best tool for the job. You may want to consider using Windows Task Scheduler (TS) instead. With TS, you can setup a schedule to say run your app and carry out the workflow, or if your program must run all the time, trigger another process that communicates with your app somehow.
If the process is not doing anything until the next interval then it's best to just simply kill the app. That way you won't be wasting threads or processes twiddling their thumbs over exorbitant delays waiting for the next interval to do something.
You can use the Microsoft Task Scheduler v2 COM Library from c# to setup your schedules or do so manually from the TS UI itself.
I'm using a System.Threading.Timer which is configured to expire in 100ms. Typically it will call the callback method within 10ms of the expected time, however, the callback is frequently called up to 500ms late. By frequent, I mean around 25% of the time.
Can anybody explain this?
Well, 500 msec is in fact a magic number in a .NET program. That's how often the threadpool manager considers adding another thread to the pool because the existing ones appear to be stuck and not making progress. The Timer callback is made on a tp thread.
So, sight unseen, a conclusion you can draw is that the callback cannot run soon enough because you have far too many threadpool threads active in your program. So the timer callback only gets a chance to run when the tp manager forcibly adds another thread to the pool.
If accurate, this is pretty unhealthy. Could be that you have a lot of tp threads that are burning 100% core. Easy to see from Task Manager, you'll see the CPU usage completely pegged at 100%. But far more common is that they are not being used effectively, instead of executing code they are blocking. Most typically on an I/O request, a socket read or dbase query for example. Such code should not run on a tp thread, it should run on a regular Thread or a Task that was configured with TaskCreationOptions.LongRunning. Or made more efficient by making it asynchronous, the C# v5 asych/await keywords can make that a lot easier.
A sledge-hammer solution is to call ThreadPool.SetMinThreads() and bump up the minimum. Only ever consider this if you cannot afford the time to do it right.
It's quite simple:
1) your OS is not RTOS (RealTime OS)
2) System.Threading.Timer executes its callback on thread from ThreadPool and it can guarantee only the fact that callback will be called after time interval elapsed.
I am working on a project in C#.NET using the .NET framework version 3.5.
My project has a class called Focuser.cs which represents a physical device, a telescope focuser, that can communicate with a PC via a serial (RS-232) port. My class (Focuser) has properties such as CurrentPosition, CurrentTemperature, ect which represents the current conditions of the focuser which can change at any time. So, my Focuser class needs to continually poll the device for these values and update its internal fields. My question is, what is the best way to perform this continual polling sequence? Occasionally, the user will need to switch the device into a different mode which will require the ability to stop the polling, perform some action, and then resume polling.
My first attempt was to use a time that ticks every 500ms and then calls up a background worker which polls for one position and one temperature then returns. When the timer ticks if the background worker isBusy then it just returns and tries again 500ms later. Someone suggested that I get rid of the background worker all together and just do the poll in the timer tick event. So I set the AutoReset property of the timer to false and then just restart the timer every time a poll finishes. These two techniques seemed to behave the exact same way in my application so I am not sure if one is better than the other. I also tried creating a new thread every time I want to do a poll operation using a new ThreadStart and all that. This also seemed to work fine.
I should mention one other thing. This class is part of a COM object server which basically means that the class library that is produced will be called upon via COM. I am not sure if this has any influence on the answer but I just thought I should throw it out there.
The reason I am asking all of this is that all of my test harness runs and debug builds work just fine but when I do a release build and try to make calls to my class from another application, that application freezes up and I am having a hard time determining the cause.
Any advice, suggestions, comments would be appreciated.
Thanks, Jordan
Remember that the timer hides its own background worker thread, which basically sleeps for the interval, then fires its Elapsed event. Knowing that, it makes sense just to put the polling in Elapsed. This would be the best practice IMO, rather than starting a thread from a thread. You can start and stop Timers as well, so the code that switches modes can Stop() the Timer, perform the task, then Start() it again, and the Timer doesn't even have to know the telescope IsBusy.
However, what I WOULD keep track of is whether another instance of the Elapsed event handler is still running. You could lock the Elapsed handler's code, or you could set a flag, visible from any thread, that indicates another Elapsed() event handler is still working; Elapsed event handlers that see this flag set can exit immediately, avoiding concurrency problems working with the serial port.
So it looks like you have looked at 2 options:
Timer. The Timer is non-blocking while waiting (uses another thread), so the rest of the program can continue running and be responsive. When the timer event kicks off, you simply get/update the current values.
Timer + BackgroundWorker. The background worker is also simply a separate thread. It may take longer to actually start the thread than to simply get the current values. Unless it takes a long time to get the current values and causes your program to become unresponsive, this is unnecessary complexity.
If getting values is fast enough, stick to #1 for simplicity.
If getting values is slow, #2 will work but unnecessarily has a thread start a thread. Instead, do it with only a BackgroundWorker (no Timer). Create the BackgroundWorker once and store in a variable. No need to recreate it every time. Make sure to set WorkerSupportsCancellation to true. Whenever you want to start checking values, on your main program thread do bgWorker.RunWorkerAsync(). When you want to stop, do bgWorker.CancelAsync(). Inside your DoWork method, have a loop that checks the values and does a Thread.Sleep(500). Since it's a separate thread, it won't make your program unresponsive. In the loop conditions, also check to see if the polling was cancelled and break out. You'll probably need a way to get the values back to the main thread. You can use ReportProgress() if an integer is good enough. Otherwise you can create an object to hold the content, but make sure to lock (object) { } before reading and modifying it. This is a quick summary, but if you go this route I would recommend you read: http://www.albahari.com/threading/part3.aspx#_BackgroundWorker
Is the process of contacting the telescope and getting the current values actually take long enough to warrant polling? Have you tried dropping the multithreading and just blocking while you get the current value?
To answer your question, however, I would suggest not using a background worker but an actual Thread that updates the properties continuously.
If all these properties are read only (can you set the temp of the telescope?) and there are no dependencies between them (e.g., no transactions are required to update multiple properties at once) you can drop all the blocking code and let your thread update willy-nilly while other threads access the properties.
I suggest a real, dedicated Thread rather than the thread pool just because of a lack of knowledge of what might happen when mixing background threads and COM servers. Also, apartment state might play into this; with a Thread you can try STA but you can't do that with a threadpool thread.
You say the app freezes up in a release build?
To eliminate extra variables, I'd take all the timer/multi-threaded code out of the application(just comment it out), and try it with a straightforward blocking method.
i.e. You click a button, it calls a function, that function hits the COM object for data, and then updates the UI. All in a blocking, synchronous fashion. This will tell you for sure whether it's the multi-threading code that's freezing you up, or if it's the COM interaction itself.
How about starting a background thread with ThreadPool? Then enter a loop based on a bool (While (bContinue)) that loops and does your work and then a Thread.Sleep at the end of the loop - exiting the program would include setting bContinue to false so the thread stops - perhaps hook it up to the OnStop event in a windows service
bool bRet = ThreadPool.QueueUserWorkItem(new WaitCallback(ThreadFunc));
private void ThreadFunc(object objState)
{
// enter loop
bContinue = true;
while (bContinue) {
// do stuff
// sleep
Thread.Sleep(m_iWaitTime_ms);
}
}
Scenario
I have a C# Windows Service that essentially subscribes to some events and if anything is triggered by the events, it carries out a few tasks.
The Thing...
....is that these events are monitoring processes, which I need to restart at certain times of the day.
Question
What's the best way I can go about performing this task at an exact time?
Thoughts so far are:
1)To use a timer that checks what time it is every few minutes.
2)Something that isn't a timer and doesn't suck as an implementation.
Help greatly appreciated.
Start a new thread at service start with IsBackground = true. This ensures your thread dies when your service stops, so you can simply start and forget it.
In the thread, use an endless loop with Thread.Sleep(60*1000)'s, waiting for the correct time of day to do the restart. The restart should probably be done on a new thread with IsBackground = false to prevent your service from stopping before your app is finished restarting (restricted to 30 secs or so permitted by Windows for your service to shut down). Alternatively you can spawn a separate process for the restart operation.
You could set off timers that run at particular times of the day but I would probably favour the following approach.
while (!closing)
{
if (SomethingNeedsDoingNow()) { DoIt(); }
Thread.Sleep(1);
}
This will barely consume any resources and will then be able to fire off events at any time of the day to a 1 second granularity easily.
Note SomethingNeedsDoingNow should check the current time, and see if any events need firing. If you can get away with a looser granularity then you can sleep for 60seconds instead.
One option, if you really want to avoid implementing a timer, is a windows scheduled task that kills your processed when it's fired.
You can then have your service constantly polling to make sure the processes are running, and if not start them.
Still kind of 'timer-y' granted, but it's another approach.
I want to ask if a System.Timers.Timer instance runs on a single thread, a thread pool, or something else?
If it does run on a single thread, what do you think would be best for this example:
I want to update all character's health every minute
I want to update all character's energy every 2 seconds
I want to update all character's specials every 40 seconds
Should I run them each on a separate thread, run them on a separate event, or run all of those in a single thread having to check the time differences?
I would run all the actions from a single timing thread and compute the time differences. This way I would be able to run as many actions as I would like without instantiating more timers.
It's also easier to synchronize actions which occur at the same time interval.
From http://msdn.microsoft.com/en-us/library/system.timers.aspx:
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.
System.Timers.Timer elapsed event uses Threadpool. So multiple threads can be invoked if the interval is less( and elapsed event> interval takes long time to complete). Threadpool runs in background and UI updates cannot be done outside the UI thread in windows application. You can however use Control.Invoke Control.BeginInvoke
Link
Timers
difference between invoke and begininvoke
Should I run them each on a separate thread, run them on a separate event, or run all of those in a single thread having to check the time differences.
In my opinion you should use three timers. Three is a number which should not affect the performance in a negative way.
A big disadvantage when calculating time differences are time-changes (daylight saving times, synchronisation with the Internet).
You would have to use Environment.TickCount.