I have a function that I want to invoke every x seconds, but I want it to be thread-safe.
Can I set up this behavior when I am creating the timer? (I don't mind which .NET timer I use, I just want it to be thread-safe).
I know I can implement locks inside my callback function, but I think it would be more elegant if it were in the timer level.
My callback function, and environment are not related to a UI.
[Edit 1] I just don't want there to be more than one thread inside my callback function.
[Edit 2] I want to keep the locking inside the timer level, because the timer is responsible for when to call my callback, and here there is a particular situation when I don't want to call my callback function. So I think when to call is the responsibility of the timer.
Complementing Tim Lloyd's solution for
System.Timers.Timer
, here's a solution to prevent reentrancy for cases where you want to useSystem.Threading.Timer
instead.I believe you don't want
interval
to be accessed inside of the callback, but that is be easy to fix, if you want to: Put the above into aNonReentrantTimer
class that wraps the BCL'sTimer
class. You would then pass thedoSomeWork
callback in as a parameter. An example of such a class:How timer could know about your shared data?
Timer callback is executed on some ThreadPool thread. So you will have at least 2 threads:
And it is your responsibility to provide correct work with your shared data.
Re edits: chibacity provided the perfect example.
I'm guessing, as your question is not entirely clear, that you want to ensure that your timer cannot re-enter your callback whilst you are processing a callback, and you want to do this without locking. You can achieve this using a
System.Timers.Timer
and ensuring that theAutoReset
property is set to false. This will ensure that you have to trigger the timer on each interval manually, thus preventing any reentrancy:If locking is necessary then how could a timer arrange that? You're looking for a magical freebie.
Re Edit1:
Your choices are System.Timers.Timer and System.Threading.Timer, both need precautions against re-entrance. See this page and look for the Dealing with Timer Event Reentrance section.