C# timer callback - c#

if I set a timer like this:
var MyTimer = new Timer(RunTask, AutoEvent, 1000, 2000);
is it guaranteed that RunTask will always be run on the same thread?
all my tests seem to indicate that it is the case, but is it a guarantee or luck?
this is quite important since I need to store variables that persist call to call and I'm currently using the [ThreadStatic] attribute on them.
I know that if the call back is holding the thread longer than the timer delay, the timer will do another callback on another thread; so I narrow the question to the case where there are no parallel runs (I block teh timer during the callback).

The System.Threading.TimerCallback delegate allows you to pass a context object to the callback method. You can use this context object to pass the state that you need in the callback handler. This way it wont matter what thread you are called back on, as you won't need to use ThreadStatic.
The state argument that you pass to the Timer constructor will be passed to the callback method.

To answer your question, no there is no such thing as a "reserved" thread for the TimerCallback. The event is scheduled on a ThreadPool and there is no guarantee that the next tick will happen on the same thread, even tho it is possible.
A simple test illustrates this:
myTimer = new System.Threading.Timer(timer_Elapsed, null, 0, Timeout.Infinite);
static void timer_Elapsed(object state)
{
Thread.Sleep(100);
Console.WriteLine(Thread.CurrentThread.ManagedThreadId);
myTimer.Change(100, Timeout.Infinite);
}
And the results:

Related

When to use and what is the difference of a timer and thread?

Just now have some confusion about timer and thread, see below example, Both codes provide the same result (Do some checking every 60 seconds), so when should I use a timer and when should I use a thread to handle jobs when they're providing the same result?
Use Thread:
Thread checkJob = new Thread(checkStatus);
checkJob.Start();
protected void checkStatus()
{
//Do Checking here
Thread.Sleep(60000);
}
Use Timer:
public Form1()
{
InitializeComponent();
Timer time = new Timer();
time.Interval = 60000;
time.Tick += time_Tick;
time.Enabled = true;
}
void time_Tick(object sender, EventArgs e)
{
//Do Checking here
}
If the task that is performed periodically is very short, and will not get in the way of processing on the thread that the timer runs, then a timer is a reasonable choice.
On the other hand, if the periodic task takes a significant amount of time, and you cannot afford to have the main thread interrupted to perform it, then a separate dedicated thread is a good choice.
It depends on the timer you're using. If you're using a WinForms timer then your callback will fire on the gui thread. If you've got a lot of work to do then this will cause your application to block until you've finished, which will make for a bad user experience.
If you're using one of the other timers then they'll fire on a thread in the thread pool. Even here you'll want to avoid doing anything to long, but it won't block your gui thread. However, you're need to ensure you marshal any calls into the gui using the BeginInvoke method.
Starting your own thread is good if you're got long running tasks to do every time the timer fires, but once again you'll want to marshal calls back to the gui thread. Rather than using Thread.Sleep it's better to use an Event so that you can detect when the rest of the system is shutting down:
ManualResetEvent stopEvent = new ManualResetEvent(false);
Thread checkJob = new Thread(checkStatus);
checkJob.Start();
protected void checkStatus()
{
//Do Checking here
while(stopEvent.Wait(60000) == false)
{
// Do processing
}
}
Now you can stop the thread by calling stopEvent.Set()
You can view a thread as a "sub-process"; a process can have multiple threads, allowing it to perform several operations in parallel. A thread is an expensive system resource; it uses a CPU when it's active, and allocates its own call stack (1MB by default). Using a thread to perform periodic actions is a waste of precious resources, and doesn't scale well.
A timer, in the other hand, is much cheaper. It's just a time-controlled trigger that does nothing most of the time, except when it's time to execute your code. It's the right choice in your case.
I would recommend to use Timer - it is more suitable when it comes to resource consumption.
Setting up a new thread is quite expansive.
By the way in case you would like to use Thread you should set it to IsBackground=true, so that it can finish its execution when the application is shutdown.

How to set a timeout for a dynamically loaded method

Description: I am using Type.InvokeMember to call a method from a dynamically loaded library. Sometimes, this method hangs and does not release its resources. In addition, the method does not take a timeout as a parameter.
How can I set a timeout for this method, STOP the method from running in the background, and move on to the next step?
Any help would be appreciated!
Props to #lightbricko as his methodology will give you the abort functionality you need.
As far as a timeout is concerned, it may be easier to provide a wrapper class for monitoring the time and invoking the solution on a separate thread.
Your question fails to mention if there is a return value, or a requirement for synchronicity. I'll present a solution with increasing levels of complexity depending on the requirements. Please respond to this thread if you need me to flesh out the more complex solutions.
Not in my IDE, so I whipped this up in Notepad. Its a bit dirty but should give you a skeleton to work from.
You can pass in the necessary parameters for invoking the method. For bonus points check out Action and Function delegates! :)
public class TimedRemoteInvocation
{
Timer myTimer;
Thread myThread;
public static RemoteInvocationTimer Invoke(..., int timeout)
{
return new RemoteInvocationTimer().InvokeMember(...)
}
private RemoteInvocationTimer InvokeMember( ..., int timeout )
{
myTimer = new Timer();
myTimer.Elapsed += new ElapsedEventHandler( TimeOutOccurred );
myTimer.Interval = timeout; //ex: 200ms
myThread = new Thread(
new ThreadStart(theTypeObj.InvokeMember(...));
myTimer.Start();
mythread.start();
return this;
}
public void ElapsedEventHandler( Object sender, ElapsedEventArgs e )
{
myThread.Abort()
}
}
If you need this to appear synchronous to the caller (that is, the caller needs to wait for completion) let me know and I'll update the code.
The idea would be for the caller to wait on a lock mutex.
That lock would be grabbed first by the TimedRemoteInvocation class, and released when the operation completes. Again I can provide more info if you need it.
TimedRemoteInvocation caller = TimedRemoteInvocation.Invoke(...)
lock(caller.sharedLock) {}
The final variation expects a result from the invoked method.
This can be easily captured but returning that value to the caller would either require
The caller to handle an event that declares a result
Should synchronicity be required, the result can be stored in a property of the TimedRemoteInvocation class (again the use of a mutex lock would be required).
TimedRemoteInvocation caller = TimedRemoteInvocation.Invoke(...)
res = caller.Result //The result property will grab/wait on the mutex and halt the caller.
There's a lot to unpack here and I know I'm glossing over things, so let me know if you need me to add to anything.
You can either spawn a new Thread and abort it when needed or you can create a new AppDomain and unload it when needed.
Using an AppDomain provides more isolation.

Will the threadpool queue a timer's callback function, sometimes scheduling more than one thread at the same time?

In the following code TimerRecalcStatisticsElapsed should only have one instance of it running. The worker methods that this callback invokes is made to run in sequence, with a maximum of one thread running at a time.
Question Part 1:
If the timer's callback runs an a threadpool thread (as opposed to running the callback on a separate thread), is it correct to say the the threadpool might queue and defer the thread for later execution based on conditions (MaxThreads reached, threadpool internal logic)?
Question Part 2:
Assuming it's possible for one timer callback to be queued for anything but immediate execution, does that mean that any number of thread callbacks may execute concurrently?
Question Part 3
Assuming part 2 is true, does that mean the code below can ever have more than one callback operating at the same time?
The reason I'm asking is because there are several thousand instances of this class running on a multi-CPU server. I'm also seeing data corruption consistent with an out-of-order operation of // Do Work Here.
Aside
// Do work here internally works with a System.Collections.Dictionary and edits the values of y. It also removes some keys for a subsequent function that is called serially. That function is missing keys (x) that were previously present in the first call. I think this is because there is a race condition with the final statement obj.cleanupdata()
public class SystemTimerTest
{
readonly System.Timers.Timer timerRecalcStatistics;
readonly System.Diagnostics.Stopwatch stopwatchForRecalcStatistics = new System.Diagnostics.Stopwatch();
public SystemTimerTest(TimeSpan range, DataOverwriteAction action)
{
int recalculateStatisticsEveryXMillseconds = 1000;
timerRecalcStatistics = new System.Timers.Timer(recalculateStatisticsEveryXMillseconds);
timerRecalcStatistics.AutoReset = true;
timerRecalcStatistics.Elapsed += new System.Timers.ElapsedEventHandler(TimerRecalcStatisticsElapsed);
timerRecalcStatistics.Interval = recalculateStatisticsEveryXMillseconds;
timerRecalcStatistics.Enabled = true;
this.maxRange = range;
this.hashRunningTotalDB = new HashRunningTotalDB(action);
this.hashesByDate = new HashesByDate(action);
this.dataOverwriteAction = action;
}
private void TimerRecalcStatisticsElapsed(object source, System.Timers.ElapsedEventArgs e)
{
stopwatchForRecalcStatistics.Start();
Console.WriteLine("The TimerRecalcStatisticsElapsed event was raised at {0}", e.SignalTime.ToString("o"));
// DO WORK HERE
stopwatchForRecalcStatistics.Stop();
double timeBuffer = GetInterval(IntervalTypeEnum.NearestSecond, e.SignalTime) - stopwatchForRecalcStatistics.ElapsedMilliseconds;
if (timeBuffer > 0)
timerRecalcStatistics.Interval = timeBuffer;
else
timerRecalcStatistics.Interval = 1;
stopwatchForRecalcStatistics.Reset();
timerRecalcStatistics.Enabled = true;
}
}
ad 1) It is not important whether ThreadPool can defer execution of callback method, because anyway callback is not guaranteed to complete execution before another timer interval(s) elapses (thread can be suspended by thread scheduler for example, or callback might call long-running function).
ad 2) This is what MSDN says about Timer class:
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.
So the answer is YES, callback can be executing on multiple threads concurrently.
ad 3) YES. And you should either avoid using shared resources (timerRecalcStatistics, stopwatchForRecalcStatistics) in callback method, or synchronize access to these shared resources (for example with lock), or set appropriate object to Timer's SynchronizingObject property, or set AutoReset property of Timer to false (and enable timer again at the end of timer callback).
UPDATE:
I thing that Jon Skeet's answer doesn't solve your problem. Also implementing your own SynchonizingObject is IMHO more complicated than necessary (but it's hard to say without knowing whole problem). I hope this implementation should work (but I didn't tested it):
public class MySynchronizeInvoke : ISynchronizeInvoke
{
private object SyncObject = new Object();
private delegate object InvokeDelegate(Delegate method, object[] args);
public IAsyncResult BeginInvoke(Delegate method, object[] args)
{
ElapsedEventHandler handler = (ElapsedEventHandler)method;
InvokeDelegate D = Invoke;
return D.BeginInvoke(handler, args, CallbackMethod, null);
}
private void CallbackMethod(IAsyncResult ar)
{
AsyncResult result = ar as AsyncResult;
if(result != null)
((InvokeDelegate)result.AsyncDelegate).EndInvoke(ar);
}
public object EndInvoke(IAsyncResult result)
{
result.AsyncWaitHandle.WaitOne();
return null;
}
public object Invoke(Delegate method, object[] args)
{
lock(SyncObject)
{
ElapsedEventHandler handler = (ElapsedEventHandler)method;
handler(args[0], (ElapsedEventArgs)args[1]);
return null;
}
}
public bool InvokeRequired
{
get { return true; }
}
}
From the documentation on System.Timers.Timer:
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.
So to answer your questions:
Yes, it runs on a threadpool thread, and is subject to threadpool filling up and deferring like anything else. Given that the threadpool now has a maximum of hundreds of threads, this shouldn't be an issue. If it is, you have bigger problems.
Assuming that you do not set a synchronizing object or otherwise sychronize your callback, yes, multiple callback can overlap. If you give the timer a synchronizing object, it will not 'overlap' events.
The code that you provided does not synchronize it's callback in any way, and so yes it can have multiple overlapping, simultaneously executing copies of your callback. You should synchronize the method using something like a lock statement if you want all of the instances of the class to be synchronized one another, or use the SynchronizingObject of the timer if you want each individual instance of the class to only ever have one callback running at any given time.

How to estimate method execution time?

I have requirement to cancel method execution if it takes the more than two seconds to complete and restart it on another thread.
So, is there any way/call back mechanism/HACK, I can make method inform me that it crossed 2 seconds time limit?
check if network drive exists with timeout in c#
https://web.archive.org/web/20140222210133/http://kossovsky.net/index.php/2009/07/csharp-how-to-limit-method-execution-time
Async Pattern:
public static T SafeLimex<T>(Func<T> F, int Timeout, out bool Completed)
{
var iar = F.BeginInvoke(null, new object());
if (iar.AsyncWaitHandle.WaitOne(Timeout))
{
Completed = true;
return F.EndInvoke(iar);
}
F.EndInvoke(iar); //not calling EndInvoke will result in a memory leak
Completed = false;
return default(T);
}
You should create System.Threading.Timer on two seconds, and run your method in another thread and wait for callback from it, if method completes before timer runs you should dispose timer, otherwise you should abort thread in which you method are executing. This is pretty simple for example
using (new Timer(BreakFunction, true, TimeSpan.FromMinutes(2), Timeout.Infinite))
{
//TODO:here you should create another thread that will run your method
}
In BreakFunction you should abort thread that runs your methods
It would be good if you can find it. I've been looking for it too.
What I usually do is start the method in another Thread, and start a Timer with 2 seconds in this case. The first time it raises the event, just do:
if (a.IsAlive)
{
a.Abort();
}
Two important things:
The Thread declared should be visible by the method that handles the timer
When calling Abort(), it raises ThreadAbortException, so you should correctly handle it in the method.

Reliable timer in a console application

I am aware that in .NET there are three timer types (see Comparing the Timer Classes in the .NET Framework Class Library). I have chosen a threaded timer as the other types can drift if the main thread is busy, and I need this to be reliable.
The way this timer works in the control of the timer is put on another thread so it can always tick along with the work begin completed on the parent thread when it is not busy.
The issue with this timer in a console application is that while the timer is ticking along on another thread the main thread is not doing anything to the application closes.
I tried adding a while true loop, but then the main thread is too busy when the timer does go off.
You can use something like Console.ReadLine() to block the main thread, so other background threads (like timer threads) will still work. You may also use an AutoResetEvent to block the execution, then (when you need to) you can call Set() method on that AutoResetEvent object to release the main thread. Also ensure that your reference to Timer object doesn't go out of scope and garbage collected.
Consider using a ManualResetEvent to block the main thread at the end of its processing, and call Reset() on it once the timer's processing has finished. If this is something that needs to run continuously, consider moving this into a service process instead of a console app.
According to MSDN and the other answers, a minimal working example of a Console application using a System.Threading.Timer without exiting immediately :
private static void Main()
{
using AutoResetEvent autoResetEvent = new AutoResetEvent(false);
using Timer timer = new Timer(state => Console.WriteLine("One second has passed"), autoResetEvent, TimeSpan.Zero, new TimeSpan(0, 0, 1));
autoResetEvent.WaitOne();
}

Categories

Resources