Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

"Atomically" changing a System.Threading.Timer

Tags:

c#

.net

Let's say I have an existing System.Threading.Timer instance and I'd like to call Change on it to push it's firing time back:

var timer = new Timer(DelayCallback, null, 10000, Timeout.Infinite);
// ... (sometime later but before DelayCallback has executed)
timer.Change(20000, Timeout.Infinite);

I'm using this timer to perform an "idle callback" after a period of no activity. ("Idle" and "no activity" are application-defined conditions in this case...the specifics aren't terribly important.) Every time I perform an "action", I want to reset the timer so that it is always set to fire 10 seconds after that.

However, there is an inherent race condition because when I call Change, I can't tell if the Timer has already fired based on its old settings. (I can, of course, tell if my callback has happened but I can't tell if the CLR's internal timer thread has queued my callback to the threadpool and its execution is imminent.)

Now I know I can call Dispose on the timer instance and re-create it each time I need to "push it back". but this seems less efficient than just changing the existing timer. Of course it may not be...I'll run some micro-benchmarks in a bit and let you all know.

Alternatively, I can always keep track of the expected firing time (via DateTime.Now.AddSeconds(10)) and, if the original Timer fires, ignore it by checking DateTime.Now in the callback. (I have a nagging concern that this may not be 100% reliable on account of the Timer using TimeSpan and my check using DateTime...this may not be an issue but I'm not completely comfortable with it for some reason...)

My questions are:

  1. Is there a good way for me to call Timer.Change and be able to know whether I managed to change it before the callback was queued to the threadpool? (I don't think so, but it doesn't hurt to ask...)
  2. Has anyone else implemented (what I term) a "pushback timer" like this? If so, I'd love to hear how you tackled the problem.

This question is somewhat hypothetical in nature since I already have a couple of working solutions (based on Dispose and based on DateTime.Now)...I'm mainly interested in hearing performance-related suggestions (as I'll be "pushing back" the Timer VERY frequently).

Thanks!

like image 411
user42286 Avatar asked Dec 01 '08 23:12

user42286


People also ask

What is System threading timer?

System. Threading. Timer, which executes a single callback method on a thread pool thread at regular intervals. The callback method is defined when the timer is instantiated and cannot be changed.

How do you stop a timer thread?

After every specified number of seconds, a timer class function is called. start() is a function that is used to initialize a timer. To end or quit the timer, one must use a cancel() function. Importing the threading class is necessary for one to use the threading class.

Is system timers timer multithreaded?

System. Timers. Timer, which fires an event and executes the code in one or more event sinks at regular intervals. The class is intended for use as a server-based or service component in a multithreaded environment; it has no user interface and is not visible at runtime.

Is system threading timer thread safe?

Timer is not thread-safe.


1 Answers

it sounds like what you really want is the application-idle event

System.Windows.Forms.Application.Idle
like image 167
Steven A. Lowe Avatar answered Oct 25 '22 12:10

Steven A. Lowe