I want to run a process every one minute, but I have been told that the Timer is working every x minute + the time required for the process to finish. but I want the thread to work every 1 minute even though the thread process may keep working for 1 hour.
I hope you got me, so in the final image, I may have 10 threads working together.
is that possible ?
Depends on the timer. Simple test shows that System.Threading.Timer works the way you want:
var timer = new Timer(s => { "Start".Dump(); Thread.Sleep(10000); "Hi!".Dump(); },
null, 1000, 1000);
Thread.Sleep(20000);
timer.Dump();
The callback executes every second even though it takes ten seconds to execute.
This is basically because the callback for this particular timer is simply posted to the threadpool, while e.g. System.Windows.Forms.Timer is actually tied to the UI thread. Of course, if you simply start a new thread (or queue work, or start a new task etc.) in the callback of winforms timer, it will work in a similar (albeit less precise) way.
Using the right tool for the job usually makes things much easier :)
Create a Timer and on the elapse event just fire a new thread to do the work, like the below example:
public class Example
{
private static Timer aTimer;
public static void Main()
{
// Create a timer with a two second interval.
aTimer = new Timer(2000);
// Hook up the Elapsed event for the timer.
aTimer.Elapsed += OnTimedEvent;
aTimer.Enabled = true;
Console.WriteLine("Press the Enter key to exit the program... ");
Console.ReadLine();
Console.WriteLine("Terminating the application...");
}
public static void DoWork()
{
var workCounter = 0;
while (workCounter < 100)
{
Console.WriteLine("Alpha.Beta is running in its own thread." + Thread.CurrentThread.ManagedThreadId);
Thread.Sleep(1000);
workCounter++;
}
}
private static void OnTimedEvent(Object source, ElapsedEventArgs e)
{
// Create the thread object, passing in the method
// via a delegate.
var oThread = new Thread(DoWork);
// Start the thread
oThread.Start();
}
}
Since .NET 4.0 Tasks are preferred to Threads.
The overhead of Task management is minimal.
// Create a task spawning a working task every 1000 msec
var t = Task.Run(async delegate
{
while (isRunning)
{
await Task.Delay(1000);
Task.Run(() =>
{
//your work
};
}
});
I have a C# program that needs to dispatch a thread every X minutes, but only if the previously dispatched thread (from X minutes) ago is not currently still running.
A plain old Timer alone will not work (because it dispatches an event every X minutes regardless or whether or not the previously dispatched process has finished yet).
The process that's going to get dispatched varies wildly in the time it takes to perform it's task - sometimes it might take a second, sometimes it might take several hours. I don't want to start the process again if it's still processing from the last time it was started.
Can anyone provide some working C# sample code?
In my opinion the way to go in this situation is to use System.ComponentModel.BackgroundWorker class and then simply check its IsBusy property each time you want to dispatch (or not) the new thread. The code is pretty simple; here's an example:
class MyClass
{
private BackgroundWorker worker;
public MyClass()
{
worker = new BackgroundWorker();
worker.DoWork += worker_DoWork;
Timer timer = new Timer(1000);
timer.Elapsed += timer_Elapsed;
timer.Start();
}
void timer_Elapsed(object sender, ElapsedEventArgs e)
{
if(!worker.IsBusy)
worker.RunWorkerAsync();
}
void worker_DoWork(object sender, DoWorkEventArgs e)
{
//whatever You want the background thread to do...
}
}
In this example I used System.Timers.Timer, but I believe it should also work with other timers. The BackgroundWorker class also supports progress reporting and cancellation, and uses event-driven model of communication with the dispatching thread, so you don't have to worry about volatile variables and the like...
EDIT
Here's more elaborate example including cancelling and progress reporting:
class MyClass
{
private BackgroundWorker worker;
public MyClass()
{
worker = new BackgroundWorker()
{
WorkerSupportsCancellation = true,
WorkerReportsProgress = true
};
worker.DoWork += worker_DoWork;
worker.ProgressChanged += worker_ProgressChanged;
worker.RunWorkerCompleted += worker_RunWorkerCompleted;
Timer timer = new Timer(1000);
timer.Elapsed += timer_Elapsed;
timer.Start();
}
void timer_Elapsed(object sender, ElapsedEventArgs e)
{
if(!worker.IsBusy)
worker.RunWorkerAsync();
}
void worker_DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker w = (BackgroundWorker)sender;
while(/*condition*/)
{
//check if cancellation was requested
if(w.CancellationPending)
{
//take any necessary action upon cancelling (rollback, etc.)
//notify the RunWorkerCompleted event handler
//that the operation was cancelled
e.Cancel = true;
return;
}
//report progress; this method has an overload which can also take
//custom object (usually representing state) as an argument
w.ReportProgress(/*percentage*/);
//do whatever You want the background thread to do...
}
}
void worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
//display the progress using e.ProgressPercentage and/or e.UserState
}
void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if(e.Cancelled)
{
//do something
}
else
{
//do something else
}
}
}
Then, in order to cancel further execution simply call worker.CancelAsync(). Note that this is completely user-handled cancellation mechanism (it does not support thread aborting or anything like that out-of-the-box).
You can just maintain a volatile bool to achieve what you asked:
private volatile bool _executing;
private void TimerElapsed(object state)
{
if (_executing)
return;
_executing = true;
try
{
// do the real work here
}
catch (Exception e)
{
// handle your error
}
finally
{
_executing = false;
}
}
You can disable and enable your timer in its elapsed callback.
public void TimerElapsed(object sender, EventArgs e)
{
_timer.Stop();
//Do Work
_timer.Start();
}
You can just use the System.Threading.Timer and just set the Timeout to Infinite before you process your data/method, then when it completes restart the Timer ready for the next call.
private System.Threading.Timer _timerThread;
private int _period = 2000;
public MainWindow()
{
InitializeComponent();
_timerThread = new System.Threading.Timer((o) =>
{
// Stop the timer;
_timerThread.Change(-1, -1);
// Process your data
ProcessData();
// start timer again (BeginTime, Interval)
_timerThread.Change(_period, _period);
}, null, 0, _period);
}
private void ProcessData()
{
// do stuff;
}
Using the PeriodicTaskFactory from my post here
CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();
Task task = PeriodicTaskFactory.Start(() =>
{
Console.WriteLine(DateTime.Now);
Thread.Sleep(5000);
}, intervalInMilliseconds: 1000, synchronous: true, cancelToken: cancellationTokenSource.Token);
Console.WriteLine("Press any key to stop iterations...");
Console.ReadKey(true);
cancellationTokenSource.Cancel();
Console.WriteLine("Waiting for the task to complete...");
Task.WaitAny(task);
The output below shows that even though the interval is set 1000 milliseconds, each iteration doesn't start until the work of the task action is complete. This is accomplished using the synchronous: true optional parameter.
Press any key to stop iterations...
9/6/2013 1:01:52 PM
9/6/2013 1:01:58 PM
9/6/2013 1:02:04 PM
9/6/2013 1:02:10 PM
9/6/2013 1:02:16 PM
Waiting for the task to complete...
Press any key to continue . . .
UPDATE
If you want the "skipped event" behavior with the PeriodicTaskFactory simply don't use the synchronous option and implement the Monitor.TryEnter like what Bob did here https://stackoverflow.com/a/18665948/222434
Task task = PeriodicTaskFactory.Start(() =>
{
if (!Monitor.TryEnter(_locker)) { return; } // Don't let multiple threads in here at the same time.
try
{
Console.WriteLine(DateTime.Now);
Thread.Sleep(5000);
}
finally
{
Monitor.Exit(_locker);
}
}, intervalInMilliseconds: 1000, synchronous: false, cancelToken: cancellationTokenSource.Token);
The nice thing about the PeriodicTaskFactory is that a Task is returned that can be used with all the TPL API, e.g. Task.Wait, continuations, etc.
This question already has a number of good answers, including a slightly newer one that is based on some of the features in the TPL. But I feel a lack here:
The TPL-based solution a) isn't really contained wholly here, but rather refers to another answer, b) doesn't show how one could use async/await to implement the timing mechanism in a single method, and c) the referenced implementation is fairly complicated, which somewhat obfuscates the underlying relevant point to this particular question.
The original question here is somewhat vague on the specific parameters of the desired implementation (though some of that is clarified in comments). At the same time, other readers may have similar but not identical needs, and no one answer addresses the variety of design options that might be desired.
I particularly like implementing periodic behavior using Task and async/await this way, because of the way it simplifies the code. The async/await feature in particular is so valuable in taking code that would otherwise be fractured by a continuation/callback implementation detail, and preserving its natural, linear logic in a single method. But no answer here demonstrates that simplicity.
So, with that rationale motivating me to add yet another answer to this question…
To me, the first thing to consider is "what exact behavior is desired here?" The question here starts with a basic premise: that the period task initiated by the timer should not run concurrently, even if the task takes longer than the timer period. But there are multiple ways that premise can be fulfilled, including:
Don't even run the timer while the task is running.
Run the timer (this and the remaining options I'm presenting here all assume the timer continues to run during the execution of the task), but if the task takes longer than the timer period, run the task again immediately after it's completed from the previous timer tick.
Only ever initiate execution of the task on a timer tick. If the task takes longer than the timer period, don't start a new task while the current one is executed, and even once the current one has completed, don't start a new one until the next timer tick.
If the task takes longer than the timer interval, not only run the task again immediately after it's completed, but run it as many times as necessary until the task has "caught up". I.e. over time, make a best effort to execute the task once for every timer tick.
Based on the comments, I have the impression that the #3 option most closely matches the OP's original request, though it sounds like the #1 option possibly would work too. But options #2 and #4 might be preferable to someone else.
In the following code example, I have implemented these options with five different methods (two of them implement option #3, but in slightly different ways). Of course, one would select the appropriate implementation for one's needs. You likely don't need all five in one program! :)
The key point is that in all of these implementations, they naturally and in a very simple way, execute the task in a period-but-non-concurrent way. That is, they effectively implement a timer-based execution model, while ensuring that the task is only ever being executed by one thread at a time, per the primary request of the question.
This example also illustrates how CancellationTokenSource can be used to interrupt the period task, taking advantage of await to handle the exception-based model in a clean, simple way.
class Program
{
const int timerSeconds = 5, actionMinSeconds = 1, actionMaxSeconds = 7;
static Random _rnd = new Random();
static void Main(string[] args)
{
Console.WriteLine("Press any key to interrupt timer and exit...");
Console.WriteLine();
CancellationTokenSource cancelSource = new CancellationTokenSource();
new Thread(() => CancelOnInput(cancelSource)).Start();
Console.WriteLine(
"Starting at {0:HH:mm:ss.f}, timer interval is {1} seconds",
DateTime.Now, timerSeconds);
Console.WriteLine();
Console.WriteLine();
// NOTE: the call to Wait() is for the purpose of this
// specific demonstration in a console program. One does
// not normally use a blocking wait like this for asynchronous
// operations.
// Specify the specific implementation to test by providing the method
// name as the second argument.
RunTimer(cancelSource.Token, M1).Wait();
}
static async Task RunTimer(
CancellationToken cancelToken, Func<Action, TimeSpan, Task> timerMethod)
{
Console.WriteLine("Testing method {0}()", timerMethod.Method.Name);
Console.WriteLine();
try
{
await timerMethod(() =>
{
cancelToken.ThrowIfCancellationRequested();
DummyAction();
}, TimeSpan.FromSeconds(timerSeconds));
}
catch (OperationCanceledException)
{
Console.WriteLine();
Console.WriteLine("Operation cancelled");
}
}
static void CancelOnInput(CancellationTokenSource cancelSource)
{
Console.ReadKey();
cancelSource.Cancel();
}
static void DummyAction()
{
int duration = _rnd.Next(actionMinSeconds, actionMaxSeconds + 1);
Console.WriteLine("dummy action: {0} seconds", duration);
Console.Write(" start: {0:HH:mm:ss.f}", DateTime.Now);
Thread.Sleep(TimeSpan.FromSeconds(duration));
Console.WriteLine(" - end: {0:HH:mm:ss.f}", DateTime.Now);
}
static async Task M1(Action taskAction, TimeSpan timer)
{
// Most basic: always wait specified duration between
// each execution of taskAction
while (true)
{
await Task.Delay(timer);
await Task.Run(() => taskAction());
}
}
static async Task M2(Action taskAction, TimeSpan timer)
{
// Simple: wait for specified interval, minus the duration of
// the execution of taskAction. Run taskAction immediately if
// the previous execution too longer than timer.
TimeSpan remainingDelay = timer;
while (true)
{
if (remainingDelay > TimeSpan.Zero)
{
await Task.Delay(remainingDelay);
}
Stopwatch sw = Stopwatch.StartNew();
await Task.Run(() => taskAction());
remainingDelay = timer - sw.Elapsed;
}
}
static async Task M3a(Action taskAction, TimeSpan timer)
{
// More complicated: only start action on time intervals that
// are multiples of the specified timer interval. If execution
// of taskAction takes longer than the specified timer interval,
// wait until next multiple.
// NOTE: this implementation may drift over time relative to the
// initial start time, as it considers only the time for the executed
// action and there is a small amount of overhead in the loop. See
// M3b() for an implementation that always executes on multiples of
// the interval relative to the original start time.
TimeSpan remainingDelay = timer;
while (true)
{
await Task.Delay(remainingDelay);
Stopwatch sw = Stopwatch.StartNew();
await Task.Run(() => taskAction());
long remainder = sw.Elapsed.Ticks % timer.Ticks;
remainingDelay = TimeSpan.FromTicks(timer.Ticks - remainder);
}
}
static async Task M3b(Action taskAction, TimeSpan timer)
{
// More complicated: only start action on time intervals that
// are multiples of the specified timer interval. If execution
// of taskAction takes longer than the specified timer interval,
// wait until next multiple.
// NOTE: this implementation computes the intervals based on the
// original start time of the loop, and thus will not drift over
// time (not counting any drift that exists in the computer's clock
// itself).
TimeSpan remainingDelay = timer;
Stopwatch swTotal = Stopwatch.StartNew();
while (true)
{
await Task.Delay(remainingDelay);
await Task.Run(() => taskAction());
long remainder = swTotal.Elapsed.Ticks % timer.Ticks;
remainingDelay = TimeSpan.FromTicks(timer.Ticks - remainder);
}
}
static async Task M4(Action taskAction, TimeSpan timer)
{
// More complicated: this implementation is very different from
// the others, in that while each execution of the task action
// is serialized, they are effectively queued. In all of the others,
// if the task is executing when a timer tick would have happened,
// the execution for that tick is simply ignored. But here, each time
// the timer would have ticked, the task action will be executed.
//
// If the task action takes longer than the timer for an extended
// period of time, it will repeatedly execute. If and when it
// "catches up" (which it can do only if it then eventually
// executes more quickly than the timer period for some number
// of iterations), it reverts to the "execute on a fixed
// interval" behavior.
TimeSpan nextTick = timer;
Stopwatch swTotal = Stopwatch.StartNew();
while (true)
{
TimeSpan remainingDelay = nextTick - swTotal.Elapsed;
if (remainingDelay > TimeSpan.Zero)
{
await Task.Delay(remainingDelay);
}
await Task.Run(() => taskAction());
nextTick += timer;
}
}
}
One final note: I came across this Q&A after following it as a duplicate of another question. In that other question, unlike here, the OP had specifically noted they were using the System.Windows.Forms.Timer class. Of course, this class is used mainly because it has the nice feature that the Tick event is raised in the UI thread.
Now, both it and this question involve a task that is actually executed in a background thread, so the UI-thread-affinitied behavior of that timer class isn't really of particular use in those scenarios. The code here is implemented to match that "start a background task" paradigm, but it can easily be changed so that the taskAction delegate is simply invoked directly, rather than being run in a Task and awaited. The nice thing about using async/await, in addition to the structural advantage I noted above, is that it preserves the thread-affinitied behavior that is desirable from the System.Windows.Forms.Timer class.
You can stop timer before the task and start it again after task completion this can make your take perform periodiacally on even interval of time.
public void myTimer_Elapsed(object sender, EventArgs e)
{
myTimer.Stop();
// Do something you want here.
myTimer.Start();
}
If you want the timer's callback to fire on a background thread, you could use a System.Threading.Timer. This Timer class allows you to "Specify Timeout.Infinite to disable periodic signaling." as part of the constructor, which causes the timer to fire only a single time.
You can then construct a new timer when your first timer's callback fires and completes, preventing multiple timers from being scheduled until you are ready for them to occur.
The advantage here is you don't create timers, then cancel them repeatedly, as you're never scheduling more than your "next event" at a time.
There are at least 20 different ways to accomplish this, from using a timer and a semaphore, to volatile variables, to using the TPL, to using an opensource scheduling tool like Quartz etc al.
Creating a thread is an expensive exercise, so why not just create ONE and leave it running in the background, since it will spend the majority of its time IDLE, it causes no real drain on the system. Wake up periodically and do work, then go back to sleep for the time period. No matter how long the task takes, you will always wait at least the "waitForWork" timespan after completing before starting a new one.
//wait 5 seconds for testing purposes
static TimeSpan waitForWork = new TimeSpan(0, 0, 0, 5, 0);
static ManualResetEventSlim shutdownEvent = new ManualResetEventSlim(false);
static void Main(string[] args)
{
System.Threading.Thread thread = new Thread(DoWork);
thread.Name = "My Worker Thread, Dude";
thread.Start();
Console.ReadLine();
shutdownEvent.Set();
thread.Join();
}
public static void DoWork()
{
do
{
//wait for work timeout or shudown event notification
shutdownEvent.Wait(waitForWork);
//if shutting down, exit the thread
if(shutdownEvent.IsSet)
return;
//TODO: Do Work here
} while (true);
}
You can use System.Threading.Timer. Trick is to set the initial time only. Initial time is set again when previous interval is finished or when job is finished (this will happen when job is taking longer then the interval). Here is the sample code.
class Program
{
static System.Threading.Timer timer;
static bool workAvailable = false;
static int timeInMs = 5000;
static object o = new object();
static void Main(string[] args)
{
timer = new Timer((o) =>
{
try
{
if (workAvailable)
{
// do the work, whatever is required.
// if another thread is started use Thread.Join to wait for the thread to finish
}
}
catch (Exception)
{
// handle
}
finally
{
// only set the initial time, do not set the recurring time
timer.Change(timeInMs, Timeout.Infinite);
}
});
// only set the initial time, do not set the recurring time
timer.Change(timeInMs, Timeout.Infinite);
}
Why not use a timer with Monitor.TryEnter()? If OnTimerElapsed() is called again before the previous thread finishes, it will just be discarded and another attempt won't happen again until the timer fires again.
private static readonly object _locker = new object();
private void OnTimerElapsed(object sender, ElapsedEventArgs e)
{
if (!Monitor.TryEnter(_locker)) { return; } // Don't let multiple threads in here at the same time.
try
{
// do stuff
}
finally
{
Monitor.Exit(_locker);
}
}
I had the same problem some time ago and all I had done was using the lock{} statement. With this, even if the Timer wants to do anything, he is forced to wait, until the end of the lock-Block.
i.e.
lock
{
// this code will never be interrupted or started again until it has finished
}
This is a great way to be sure, your process will work until the end without interrupting.
If I understand you correctly, you actually just want to ensure your thread is not running before you dispatch another thread. Let's say you have a thread defined in your class like so.
private System.Threading.Thread myThread;
You can do:
//inside some executed method
System.Threading.Timer t = new System.Threading.Timer(timerCallBackMethod, null, 0, 5000);
then add the callBack like so
private void timerCallBackMethod(object state)
{
if(myThread.ThreadState == System.Threading.ThreadState.Stopped || myThread.ThreadState == System.Threading.ThreadState.Unstarted)
{
//dispatch new thread
}
}
This should do what you want. It executes a thread, then joins the thread until it has finished. Goes into a timer loop to make sure it is not executing a thread prematurely, then goes off again and executes.
using System.Threading;
public class MyThread
{
public void ThreadFunc()
{
// do nothing apart from sleep a bit
System.Console.WriteLine("In Timer Function!");
Thread.Sleep(new TimeSpan(0, 0, 5));
}
};
class Program
{
static void Main(string[] args)
{
bool bExit = false;
DateTime tmeLastExecuted;
// while we don't have a condition to exit the thread loop
while (!bExit)
{
// create a new instance of our thread class and ThreadStart paramter
MyThread myThreadClass = new MyThread();
Thread newThread = new Thread(new ThreadStart(myThreadClass.ThreadFunc));
// just as well join the thread until it exits
tmeLastExecuted = DateTime.Now; // update timing flag
newThread.Start();
newThread.Join();
// when we are in the timing threshold to execute a new thread, we can exit
// this loop
System.Console.WriteLine("Sleeping for a bit!");
// only allowed to execute a thread every 10 seconds minimum
while (DateTime.Now - tmeLastExecuted < new TimeSpan(0, 0, 10));
{
Thread.Sleep(100); // sleep to make sure program has no tight loops
}
System.Console.WriteLine("Ok, going in for another thread creation!");
}
}
}
Should produce something like:
In Timer Function!
Sleeping for a bit!
Ok, going in for another thread creation!
In Timer Function!
Sleeping for a bit!
Ok, going in for another thread creation!
In Timer Function!
...
...
Hope this helps!
SR
The guts of this is the ExecuteTaskCallback method. This bit is charged with doing some work, but only if it is not already doing so. For this I have used a ManualResetEvent (canExecute) that is initially set to be signalled in the StartTaskCallbacks method.
Note the way I use canExecute.WaitOne(0). The zero means that WaitOne will return immediately with the state of the WaitHandle (MSDN). If the zero is omitted, you would end up with every call to ExecuteTaskCallback eventually running the task, which could be fairly disastrous.
The other important thing is to be able to end processing cleanly. I have chosen to prevent the Timer from executing any further methods in StopTaskCallbacks because it seems preferable to do so while other work may be ongoing. This ensures that both no new work will be undertaken, and that the subsequent call to canExecute.WaitOne(); will indeed cover the last task if there is one.
private static void ExecuteTaskCallback(object state)
{
ManualResetEvent canExecute = (ManualResetEvent)state;
if (canExecute.WaitOne(0))
{
canExecute.Reset();
Console.WriteLine("Doing some work...");
//Simulate doing work.
Thread.Sleep(3000);
Console.WriteLine("...work completed");
canExecute.Set();
}
else
{
Console.WriteLine("Returning as method is already running");
}
}
private static void StartTaskCallbacks()
{
ManualResetEvent canExecute = new ManualResetEvent(true),
stopRunning = new ManualResetEvent(false);
int interval = 1000;
//Periodic invocations. Begins immediately.
Timer timer = new Timer(ExecuteTaskCallback, canExecute, 0, interval);
//Simulate being stopped.
Timer stopTimer = new Timer(StopTaskCallbacks, new object[]
{
canExecute, stopRunning, timer
}, 10000, Timeout.Infinite);
stopRunning.WaitOne();
//Clean up.
timer.Dispose();
stopTimer.Dispose();
}
private static void StopTaskCallbacks(object state)
{
object[] stateArray = (object[])state;
ManualResetEvent canExecute = (ManualResetEvent)stateArray[0];
ManualResetEvent stopRunning = (ManualResetEvent)stateArray[1];
Timer timer = (Timer)stateArray[2];
//Stop the periodic invocations.
timer.Change(Timeout.Infinite, Timeout.Infinite);
Console.WriteLine("Waiting for existing work to complete");
canExecute.WaitOne();
stopRunning.Set();
}
I recommend to use Timer instead of thread, as it's lighter object. To achieve your goal you can do following.
using System.Timers;
namespace sample_code_1
{
public class ClassName
{
Timer myTimer;
static volatile bool isRunning;
public OnboardingTaskService()
{
myTimer= new Timer();
myTimer.Interval = 60000;
myTimer.Elapsed += myTimer_Elapsed;
myTimer.Start();
}
private void myTimer_Elapsed(object sender, ElapsedEventArgs e)
{
if (isRunning) return;
isRunning = true;
try
{
//Your Code....
}
catch (Exception ex)
{
//Handle Exception
}
finally { isRunning = false; }
}
}
}
Let me know if it helps.
I wanted a timer with the following properties:
No matter how many times start is called, only one call back thread is ever running
The time spent in the call back function was ignored with regards to the interval. E.g if the interval is 100ms and the call back takes 4000ms to execute, the callback is called at 100ms, 4100ms etc.
I couldn't see anything available so wrote the following code. Is there a better way to do this?
/**
* Will ensure that only one thread is ever in the callback
*/
public class SingleThreadedTimer : Timer
{
protected static readonly object InstanceLock = new object();
//used to check whether timer has been disposed while in call back
protected bool running = false;
virtual new public void Start()
{
lock (InstanceLock)
{
this.AutoReset = false;
this.Elapsed -= new ElapsedEventHandler(SingleThreadedTimer_Elapsed);
this.Elapsed += new ElapsedEventHandler(SingleThreadedTimer_Elapsed);
this.running = true;
base.Start();
}
}
virtual public void SingleThreadedTimer_Elapsed(object sender, ElapsedEventArgs e)
{
lock (InstanceLock)
{
DoSomethingCool();
//check if stopped while we were waiting for the lock,
//we don't want to restart if this is the case..
if (running)
{
this.Start();
}
}
}
virtual new public void Stop()
{
lock (InstanceLock)
{
running = false;
base.Stop();
}
}
}
Here's a quick example I just knocked up;
using System.Threading;
//...
public class TimerExample
{
private System.Threading.Timer m_objTimer;
private bool m_blnStarted;
private readonly int m_intTickMs = 1000;
private object m_objLockObject = new object();
public TimerExample()
{
//Create your timer object, but don't start anything yet
m_objTimer = new System.Threading.Timer(callback, m_objTimer, Timeout.Infinite, Timeout.Infinite);
}
public void Start()
{
if (!m_blnStarted)
{
lock (m_objLockObject)
{
if (!m_blnStarted) //double check after lock to be thread safe
{
m_blnStarted = true;
//Make it start in 'm_intTickMs' milliseconds,
//but don't auto callback when it's done (Timeout.Infinite)
m_objTimer.Change(m_intTickMs, Timeout.Infinite);
}
}
}
}
public void Stop()
{
lock (m_objLockObject)
{
m_blnStarted = false;
}
}
private void callback(object state)
{
System.Diagnostics.Debug.WriteLine("callback invoked");
//TODO: your code here
Thread.Sleep(4000);
//When your code has finished running, wait 'm_intTickMs' milliseconds
//and call the callback method again,
//but don't auto callback (Timeout.Infinite)
m_objTimer.Change(m_intTickMs, Timeout.Infinite);
}
}
The .NET Framework provides four timers. Two of these are general-purpose multithreaded
timers:
System.Threading.Timer
System.Timers.Timer
The other two are special-purpose single-threaded timers:
System.Windows.Forms.Timer (Windows Forms timer)
System.Windows.Threading.DispatcherTimer (WPF timer)
The last 2 are designed to eliminate thread-safety issues for WPF and Windows Forms applications.
For example, using WebBrowser inside a timer to capture screenshots from webpage needs to be single-threaded and gives an error at runtime if it is on another thread.
The single-thread timers have the following benefits
You can forget about thread safety.
A fresh Tick will never fire until the previous Tick has finished
processing.
You can update user interface elements and controls directly from
Tick event handling code, without calling Control.BeginInvoke or
Dispatcher.BeginIn voke.
and main disadvantage to note
One thread serves all timers—as well as the processing UI events.
Which means that the Tick event handler must execute quickly,
otherwise the user interface becomes unresponsive.
source: most are scraps from C# in a Nutshell book -> Chapter 22 -> Advanced threading -> Timers -> Single-Threaded Timers
For anyone who needs a single thread timer and wants the timer start to tick after task done.
System.Timers.Timer could do the trick without locking or [ThreadStatic]
System.Timers.Timer tmr;
void InitTimer(){
tmr = new System.Timers.Timer();
tmr.Interval = 300;
tmr.AutoReset = false;
tmr.Elapsed += OnElapsed;
}
void OnElapsed( object sender, System.Timers.ElapsedEventArgs e )
{
backgroundWorking();
// let timer start ticking
tmr.Enabled = true;
}
Credit to Alan N
source https://www.codeproject.com/Answers/405715/System-Timers-Timer-single-threaded-usage#answer2
Edit: spacing
Look at the [ThreadStatic] attribute and the .Net 4.0 ThreadLocal generic type. This will probably quickly give you a way to code this without messing with thread locking etc.
You could have a stack inside your time class, and you could implement a Monitor() method that returns a IDisposable, so you can use the timer like so:
using (_threadTimer.Monitor())
{
// do stuff
}
Have the timer-monitor pop the the interval timestamp off the stack during Dispose().
Manually coding all the locking and thread recognition is an option as has been mentioned. However, locking will influence the time used, most likely more than having to initialize an instance per thread using ThreadLocal
If you're interested, I might knock up an example later
Here is a simple PeriodicNonOverlappingTimer class, that provides just the requested features, and nothing more than that. This timer cannot be started and stopped on demand, and neither can have its interval changed. It just invokes the specified action periodically in a non overlapping manner, until the timer is disposed.
/// <summary>
/// Invokes an action on the ThreadPool at specified intervals, ensuring
/// that the invocations will not overlap, until the timer is disposed.
/// </summary>
public class PeriodicNonOverlappingTimer : IDisposable, IAsyncDisposable
{
private readonly System.Threading.Timer _timer;
public PeriodicNonOverlappingTimer(Action periodicAction,
TimeSpan dueTime, TimeSpan period)
{
// Arguments validation omitted
_timer = new(_ =>
{
var stopwatch = Stopwatch.StartNew();
periodicAction();
var nextDueTime = period - stopwatch.Elapsed;
if (nextDueTime < TimeSpan.Zero) nextDueTime = TimeSpan.Zero;
try { _timer.Change(nextDueTime, Timeout.InfiniteTimeSpan); }
catch (ObjectDisposedException) { } // Ignore this exception
});
_timer.Change(dueTime, Timeout.InfiniteTimeSpan);
}
public void Dispose() => _timer.DisposeAsync().AsTask().Wait();
public ValueTask DisposeAsync() => _timer.DisposeAsync();
}
Usage example. Shows how to create a non-overlapping timer that starts immediately, with a period of 10 seconds.
var timer = new PeriodicNonOverlappingTimer(() =>
{
DoSomethingCool();
}, TimeSpan.Zero, TimeSpan.FromSeconds(10));
//...
timer.Dispose(); // Stop the timer once and for all
In case the DoSomethingCool fails, the exception will be thrown on the ThreadPool, causing the process to crash. So you may want to add a try/catch block, and handle all the exceptions that may occur.
The Dispose is a potentially blocking method. If the periodicAction is currently running, the Dispose will block until the last invocation is completed.
If you don't want to wait for this to happen, you can do this instead:
_ = timer.DisposeAsync(); // Stop the timer without waiting it to finish
Locked. This question and its answers are locked because the question is off-topic but has historical significance. It is not currently accepting new answers or interactions.
I need to create some windows service which will execute every N period of time.
The question is:
Which timer control should I use: System.Timers.Timer or System.Threading.Timer one? Does it influence on something?
I am asking because I heard many evidences to non correct work of System.Timers.Timer in windows services.
Thank you.
Both System.Timers.Timer and System.Threading.Timer will work for services.
The timers you want to avoid are System.Web.UI.Timer and System.Windows.Forms.Timer, which are respectively for ASP applications and WinForms. Using those will cause the service to load an additional assembly which is not really needed for the type of application you are building.
Use System.Timers.Timer like the following example (also, make sure that you use a class level variable to prevent garbage collection, as stated in Tim Robinson's answer):
using System;
using System.Timers;
public class Timer1
{
private static System.Timers.Timer aTimer;
public static void Main()
{
// Normally, the timer is declared at the class level,
// so that it stays in scope as long as it is needed.
// If the timer is declared in a long-running method,
// KeepAlive must be used to prevent the JIT compiler
// from allowing aggressive garbage collection to occur
// before the method ends. (See end of method.)
//System.Timers.Timer aTimer;
// Create a timer with a ten second interval.
aTimer = new System.Timers.Timer(10000);
// Hook up the Elapsed event for the timer.
aTimer.Elapsed += new ElapsedEventHandler(OnTimedEvent);
// Set the Interval to 2 seconds (2000 milliseconds).
aTimer.Interval = 2000;
aTimer.Enabled = true;
Console.WriteLine("Press the Enter key to exit the program.");
Console.ReadLine();
// If the timer is declared in a long-running method, use
// KeepAlive to prevent garbage collection from occurring
// before the method ends.
//GC.KeepAlive(aTimer);
}
// Specify what you want to happen when the Elapsed event is
// raised.
private static void OnTimedEvent(object source, ElapsedEventArgs e)
{
Console.WriteLine("The Elapsed event was raised at {0}", e.SignalTime);
}
}
/* This code example produces output similar to the following:
Press the Enter key to exit the program.
The Elapsed event was raised at 5/20/2007 8:42:27 PM
The Elapsed event was raised at 5/20/2007 8:42:29 PM
The Elapsed event was raised at 5/20/2007 8:42:31 PM
...
*/
If you choose System.Threading.Timer, you can use as follows:
using System;
using System.Threading;
class TimerExample
{
static void Main()
{
AutoResetEvent autoEvent = new AutoResetEvent(false);
StatusChecker statusChecker = new StatusChecker(10);
// Create the delegate that invokes methods for the timer.
TimerCallback timerDelegate =
new TimerCallback(statusChecker.CheckStatus);
// Create a timer that signals the delegate to invoke
// CheckStatus after one second, and every 1/4 second
// thereafter.
Console.WriteLine("{0} Creating timer.\n",
DateTime.Now.ToString("h:mm:ss.fff"));
Timer stateTimer =
new Timer(timerDelegate, autoEvent, 1000, 250);
// When autoEvent signals, change the period to every
// 1/2 second.
autoEvent.WaitOne(5000, false);
stateTimer.Change(0, 500);
Console.WriteLine("\nChanging period.\n");
// When autoEvent signals the second time, dispose of
// the timer.
autoEvent.WaitOne(5000, false);
stateTimer.Dispose();
Console.WriteLine("\nDestroying timer.");
}
}
class StatusChecker
{
int invokeCount, maxCount;
public StatusChecker(int count)
{
invokeCount = 0;
maxCount = count;
}
// This method is called by the timer delegate.
public void CheckStatus(Object stateInfo)
{
AutoResetEvent autoEvent = (AutoResetEvent)stateInfo;
Console.WriteLine("{0} Checking status {1,2}.",
DateTime.Now.ToString("h:mm:ss.fff"),
(++invokeCount).ToString());
if(invokeCount == maxCount)
{
// Reset the counter and signal Main.
invokeCount = 0;
autoEvent.Set();
}
}
}
Both examples comes from the MSDN pages.
Don't use a service for this. Create a normal application and create a scheduled task to run it.
This is the commonly held best practice. Jon Galloway agrees with me. Or maybe its the other way around. Either way, the fact is that it is not best practices to create a windows service to perform an intermittent task run off a timer.
"If you're writing a Windows Service that runs a timer, you should re-evaluate your solution."
–Jon Galloway, ASP.NET MVC community program manager, author, part time superhero
Either one should work OK. In fact, System.Threading.Timer uses System.Timers.Timer internally.
Having said that, it's easy to misuse System.Timers.Timer. If you don't store the Timer object in a variable somewhere, then it is liable to be garbage collected. If that happens, your timer will no longer fire. Call the Dispose method to stop the timer, or use the System.Threading.Timer class, which is a slightly nicer wrapper.
What problems have you seen so far?
I agree with previous comment that might be best to consider a different approach. My suggest would be write a console application and use the windows scheduler:
This will:
Reduce plumbing code that replicates scheduler behaviour
Provide greater flexibility in terms
of scheduling behaviour (e.g. only
run on weekends) with all scheduling logic abstracted from application code
Utilise the command line arguments
for parameters without having to
setup configuration values in config
files etc
Far easier to debug/test during development
Allow a support user to execute by invoking
the console application directly
(e.g. useful during support
situations)
As already stated both System.Threading.Timer and System.Timers.Timer will work. The big difference between the two is that System.Threading.Timer is a wrapper arround the other one.
System.Threading.Timer will have more exception handling while
System.Timers.Timer will swallow all the exceptions.
This gave me big problems in the past so I would always use 'System.Threading.Timer' and still handle your exceptions very well.
I know this thread is a little old but it came in handy for a specific scenario I had and I thought it worth while to note that there is another reason why System.Threading.Timer might be a good approach.
When you have to periodically execute a Job that might take a long time and you want to ensure that the entire waiting period is used between jobs or if you don't want the job to run again before the previous job has finished in the case where the job takes longer than the timer period.
You could use the following:
using System;
using System.ServiceProcess;
using System.Threading;
public partial class TimerExampleService : ServiceBase
{
private AutoResetEvent AutoEventInstance { get; set; }
private StatusChecker StatusCheckerInstance { get; set; }
private Timer StateTimer { get; set; }
public int TimerInterval { get; set; }
public CaseIndexingService()
{
InitializeComponent();
TimerInterval = 300000;
}
protected override void OnStart(string[] args)
{
AutoEventInstance = new AutoResetEvent(false);
StatusCheckerInstance = new StatusChecker();
// Create the delegate that invokes methods for the timer.
TimerCallback timerDelegate =
new TimerCallback(StatusCheckerInstance.CheckStatus);
// Create a timer that signals the delegate to invoke
// 1.CheckStatus immediately,
// 2.Wait until the job is finished,
// 3.then wait 5 minutes before executing again.
// 4.Repeat from point 2.
Console.WriteLine("{0} Creating timer.\n",
DateTime.Now.ToString("h:mm:ss.fff"));
//Start Immediately but don't run again.
StateTimer = new Timer(timerDelegate, AutoEventInstance, 0, Timeout.Infinite);
while (StateTimer != null)
{
//Wait until the job is done
AutoEventInstance.WaitOne();
//Wait for 5 minutes before starting the job again.
StateTimer.Change(TimerInterval, Timeout.Infinite);
}
//If the Job somehow takes longer than 5 minutes to complete then it wont matter because we will always wait another 5 minutes before running again.
}
protected override void OnStop()
{
StateTimer.Dispose();
}
}
class StatusChecker
{
public StatusChecker()
{
}
// This method is called by the timer delegate.
public void CheckStatus(Object stateInfo)
{
AutoResetEvent autoEvent = (AutoResetEvent)stateInfo;
Console.WriteLine("{0} Start Checking status.",
DateTime.Now.ToString("h:mm:ss.fff"));
//This job takes time to run. For example purposes, I put a delay in here.
int milliseconds = 5000;
Thread.Sleep(milliseconds);
//Job is now done running and the timer can now be reset to wait for the next interval
Console.WriteLine("{0} Done Checking status.",
DateTime.Now.ToString("h:mm:ss.fff"));
autoEvent.Set();
}
}