I know this question has been asked quite a few times on SO, but none of them have been able to fix my problem. I want to call a function every 10 seconds using threads.
I have a function that does frame processing. I want to be able to grab a frame after every 10 seconds and then process it. My research showed that it would be best to use threads for that purpose, and, as I need to perform it after a specific period of time, I would also require a timer control.
I am not able to figure out how can use threading and timers together. Moreover, I have tried using a BackgroundWorker control which, while processing, hangs up my app badly. I have also tried using a timer control and tried calling the function every 10 seconds, but in that case, if the process exceeds 10 seconds that might cause some problems.
Any examples or source code that could show me how to call a function every 10 seconds using threading will be really appreciated.
You don't necessarily need threads. You can use await/async:
public async Task DoSomethingEveryTenSeconds()
{
while (true)
{
var delayTask = Task.Delay(10000);
DoSomething();
await delayTask; // wait until at least 10s elapsed since delayTask created
}
}
In this example, the returned task will never finish; to fix that you need to use some other condition instead of true.
In an application with a GUI, this will execute DoSomething on the UI thread via the message loop, like any other event (like a button click handler). If there is no GUI, it will run on a thread pool thread.
Use System.Windows.Forms.Timer
private Timer timer1;
public void InitTimer()
{
timer1 = new Timer();
timer1.Tick += new EventHandler(timer1_Tick);
timer1.Interval = 10000; // in miliseconds
timer1.Start();
}
private void timer1_Tick(object sender, EventArgs e)
{
yourfunctionhere();
}
In a Windows Forms application, add a timer from Visual Studio's ToolBox, double-click it under the Designer view, and put the functionality that you want to be executed every X seconds in the function that appears. Be sure to enable the Timer in the properties view; there you can also change your interval (in milliseconds).
You can use this code if you want to run code for 10 second then stop it
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Diagnostics;
using System.Timers;
namespace Tdo
{
class Program
{
public static bool k=true;
static void Main(string[] args)
{
Timer q = new Timer(10000);
q.Elapsed += Q_Elapsed;
q.Start();
while(k)
{
Console.WriteLine(DateTime.Now);
}
Console.ReadKey();
}
private static void Q_Elapsed(object sender, ElapsedEventArgs e)
{
StopTheCode(ref k);
}
public static void StopTheCode(ref bool flag)
{
flag= false;
}
}
}
Here is simply write the Date time of now for 10 second and when timer elapsed it set the flag = false and the while stop but be aware those 10 second will depend on your device GHz mean number of execution of the instruction per second will vary
Related
I want to call a method after some delay when an event is raised, but any subsequent events should "restart" this delay. Quick example to illustrate, the view should be updated when scrollbar position changes, but only 1 second after the user has finished scrolling.
Now I can see many ways of implementing that, but the most intuitive would be to use Task.Delay + ContinueWith + cancellation token. However, I am experiencing some issues, more precisely subsequent calls to my function cause the TaskCanceledException exception and I started to wonder how I could get rid of that. Here is my code:
private CancellationTokenSource? _cts;
private async void Update()
{
_cts?.Cancel();
_cts = new();
await Task.Delay(TimeSpan.FromSeconds(1), _cts.Token)
.ContinueWith(o => Debug.WriteLine("Update now!"),
TaskContinuationOptions.OnlyOnRanToCompletion);
}
I have found a workaround that works pretty nicely, but I would like to make the first idea work.
private CancellationTokenSource? _cts;
private CancellationTokenRegistration? _cancellationTokenRegistration;
private void Update()
{
_cancellationTokenRegistration?.Unregister();
_cts = new();
_cancellationTokenRegistration = _cts.Token.Register(() => Debug.WriteLine("Update now!"));
_cts.CancelAfter(1000);
}
You should consider using Microsoft's Reactive Framework (aka Rx) - NuGet System.Reactive and add using System.Reactive.Linq;.
You didn't say hat UI you're using, so for Windows Forms also add System.Reactive.Windows.Forms and for WPF System.Reactive.Windows.Threading.
Then you can do this:
Panel panel = new Panel(); // assuming this is a scrollable control
IObservable<EventPattern<ScrollEventArgs>> query =
Observable
.FromEventPattern<ScrollEventHandler, ScrollEventArgs>(
h => panel.Scroll += h,
h => panel.Scroll -= h)
.Select(sea => Observable.Timer(TimeSpan.FromSeconds(1.0)).Select(_ => sea))
.Switch();
IDisposable subscription = query.Subscribe(sea => Console.WriteLine("Hello"));
The query is firing for every Scroll event and starts a one second timer. The Switch operator watches for every Timer produces and only connects to the latest one produced, thus ignoring the previous Scroll events.
And that's it.
After scrolling has a 1 second pause the word "Hello" is written to the console. If you begin scrolling again then after every further 1 second pause it fires again.
In my own experience I've dealt with lots of scenarios just like the one you describe, e.g. update something one second after the mouse stops moving etc.
For a long time I would do timer restarts just the way you describe, by cancelling an old task and starting a new one. But I never really liked how messy that was, so I came up with an alternative that I use in production code. Long-term it has proven quite reliable. It takes advantage of the captured context associated with a task. Multiple instances of TaskCanceledException no longer occur.
class WatchDogTimer
{
int _wdtCount = 0;
public TimeSpan Interval { get; set; } = TimeSpan.FromSeconds(1);
public void Restart(Action onRanToCompletion)
{
_wdtCount++;
var capturedCount = _wdtCount;
Task
.Delay(Interval)
.GetAwaiter()
.OnCompleted(() =>
{
// If the 'captured' localCount has not changed after awaiting the Interval,
// it indicates that no new 'bones' have been thrown during that interval.
if (capturedCount.Equals(_wdtCount))
{
onRanToCompletion();
}
});
}
}
Another nice perk is that it doesn't rely on platform timers and works just as well in iOS/Android as it does in WinForms/WPF.
For purposes of demonstration, this can be exercised in a quick console demo where the MockUpdateView() action is sent to the WDT 10 times at 500 ms intervals. It will only execute one time, 500 ms after the last restart is received.
static void Main(string[] args)
{
Console.Title = "Test WDT";
var wdt = new WatchDogTimer { Interval = TimeSpan.FromMilliseconds(500) };
Console.WriteLine(DateTime.Now.ToLongTimeString());
// "Update view 500 ms after the last restart."
for (int i = 0; i < 10; i++)
{
wdt.Restart(onRanToCompletion: ()=>MockUpdateView());
Thread.Sleep(TimeSpan.FromMilliseconds(500));
}
Console.ReadKey();
}
static void MockUpdateView()
{
Console.WriteLine($"Update now! WDT expired {DateTime.Now.ToLongTimeString()}");
}
}
So, with 500 ms times 10 restarts this verifies one event at 5 seconds from the start.
You can combine a state variable and a delay to avoid messing with timers or task cancelation. This is far simpler IMO.
Add this state variable to your class/form:
private DateTime _nextRefresh = DateTime.MaxValue;
And here's how you refresh:
private async void Update()
{
await RefreshInOneSecond();
}
private async Task RefreshInOneSecond()
{
_nextRefresh = DateTime.Now.AddSeconds(1);
await Task.Delay(1000);
if (_nextRefresh <= DateTime.Now)
{
_nextRefresh = DateTime.MaxValue;
Refresh();
}
}
If you call RefreshInOneSecond repeatedly, it pushes out the _nextRefresh timestamp until later, so any refreshes already in flight will do nothing.
Demo on DotNetFiddle
One approach is to create a timer and reset this whenever the user does something. For example using System.Timers.Timer
timer = new Timer(1000);
timer.SynchronizingObject = myControl; // Needs a winforms object for synchronization
timer.Elapsed += OnElapsed;
timer.Start(); // Don't forget to stop the timer whenever you are done
...
private void OnUserUpdate(){
timer.Interval = 1000; // Setting the interval will reset the timer
}
There are multiple timers to chose from, I believe the same pattern is possible with the other timers. DispatchTimer might be most suitable if you use WPF.
Note that both System.Timers.Timer and Task.Delay uses System.Threading.Timer in the background. It is possible to use this directly, just call the .Change method to reset it. But be aware that this raises the event on a taskpool thread, so you need to provide your own synchronization.
I implemented the same scenario in a JavaScript application using Timer. I believe it's the same in the .NET world. Anyway handling this use-case when the user calls a method repeatedly with Task.Delay() will put more pressure on GC & thread pool
var timer = new Timer()
{
Enabled = true,
Interval = TimeSpan.FromSeconds(5).TotalMilliseconds,
};
timer.Elapsed += (sender, eventArgs) =>
{
timer.Stop();
// do stuff
}
void OnKeyUp()
{
timer.Stop();
timer.Start();
}
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
I'm trying to make a program whereby it does something every x minutes. I have been experimenting with the Stopwatch function but it don't seem to run the code I want when the time is up.
Here's my code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Diagnostics;
using System.Threading;
namespace Testing
{
class Program
{
static void Main(string[] args)
{
Stopwatch testing = new Stopwatch();
testing.Start();
Thread.Sleep(6001);
TimeSpan ts = testing.Elapsed;
int timer = Convert.ToInt32(String.Format("{0}", ts.Seconds));
Console.Write(timer);
while (testing.Elapsed < TimeSpan.FromMinutes(8))
{
timer = Convert.ToInt32(String.Format("{0}", ts.Seconds));
if (timer % 60 == 0)
{
//run x code every 1 minutes
Console.WriteLine("1 min" + timer);
}
timer = Convert.ToInt32(String.Format("{0}", ts.Seconds));
if (timer % 120 == 0)
{
//run x code every 2 minutes
Console.WriteLine("2 min" + timer);
}
}
testing.Stop();
}
}
}
Stopwatch is a high-performance timer (usually with 100ns resolution) - it is entirely inappropriate for what you're trying to do. Stopwatch is used to measure time by taking snapshots of a system counter and then calculating the difference.
Since most of a scheduler's job is to wait until a job needs to be done, implementing a scheduler with a tight loop is extremely inefficient - the system is using CPU resources to decide to not do anything for most of the time.
To properly implement a scheduler (if that's what you're trying to do), look into using ManualResetEvent with a timeout option.
Using an event puts your current thread to sleep (so it's not using system resources while it's doing nothing) and when the timeout expires, the event is triggered and the code can call the function that you're trying to schedule.
If you want nothing else than a simple timer that tells you when an interval elapsed, use System.Timers.Timer instead: this makes it much simpler to schedule a callback (the Elapsed event is called when the timer expires) and you don't have to run a loop during the wait.
Edit:
If you simply want to call a callback function periodically, a simple timer is easier to hook up than an event. Here's a code sample using System.Timer (not my code, I copy & pasted this from MSDN, linked above):
private static Timer m_oTimer;
public static void Main ()
{
m_oTimer = new System.Timers.Timer ( 2 * 1000 * 60 ); // 2 minutes
m_oTimer.Elapsed += OnTimedEvent; // Timer callback
m_oTimer.Enabled = true; // Start timer
// Wait here (you can do other processing here, too)
Console.WriteLine ( "Press the Enter key to exit the program... " );
Console.ReadLine ();
Console.WriteLine ( "Terminating the application..." );
}
private static void OnTimedEvent ( Object source, ElapsedEventArgs e )
{
// This is called on a separate thread; do periodic processing here
Console.WriteLine ( "The Elapsed event was raised at {0}", e.SignalTime );
}
As suggested by xxbbcc, here's an implementation using ManualResetEvent.WaitOne() with a TimeOut:
static void Main(string[] args)
{
int TimeOut = (int)TimeSpan.FromMinutes(2).TotalMilliseconds;
System.Threading.ManualResetEvent mreDuration = new System.Threading.ManualResetEvent(false);
Task.Run(() => {
System.Threading.Thread.Sleep((int)TimeSpan.FromMinutes(30).TotalMilliseconds);
mreDuration.Set();
});
while(!mreDuration.WaitOne(TimeOut))
{
Console.WriteLine("Two Minutes...");
}
Console.WriteLine("Thirty Mintues!");
Console.ReadLine();
}
You should use Timer. If you want timer to stop running after, let's say, 'y' minutes, then you just store the start time in a variable and write the Timer.Stop() function so that it get executed after 'y' minutes (hint: write it in timer_tick event). Time period of the timer should be HCF of all x's and y. Remember to set time period in miliseconds.
I am implementing a comic reader in C# 4.0, and browsing from one image
to the next takes some time because of some processes I implemented.
Therefore, I implemented it in such a way that the UI thread will show
first the unprocessed image whilst the background thread is processing
the image and will later replace the unprocessed image.
It all works fine but now, some users will crazily like to click next
image continusly and this causes the background worker to processes
all those clicks and display all the images.
WHAT I WANT: if a user clicks multiple times, I want the background
worker to process the last thread only.
WHAT I HAVE DONE: Now, I have implemented a function to check the
number of active threads, if the active threads is greater than 1,
background thread will not process but returns the previous image(THAT
IS NOT GOOD, because the unprocessed image will be one index ahead)
If you have idea please explain to me like a beginner!
private void button4_Click(object sender, EventArgs e)
{
Bitmap b = new Bitmap(this.CurrImage);
if (!shutdown)
{
process_updateThread = new Thread(new ThreadStart(process_update));
process_updateThread.Start();
}
pictureBox1.Image = b; //image will be replaced by worker thread image
pictureBox1.Location = ImageEdit.CalculateLocationImage(b);
SetBackColor(b);
ShowPageCount();
updateNavButtons();
}
void StopThread()
{
if(((IEnumerable)System.Diagnostics.Process.GetCurrentProcess().Threads).OfType<System.Diagnostics.ProcessThread>()
.Where(t => t.ThreadState == System.Diagnostics.ThreadState.Running).Count() > 1)
shutdown = true;
else shutdown = false;
}
I am assuming your long running process is process_update.
You must stop all running process_updates before running the next one. But DON'T USE BOOLEAN VARIABLE TO DO THAT!!! You must use synchronizing objects. Most likely it should be ManualResetEvent.
UPDATE:
This very simple example can give you an idea of multithreading and thread management
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;
namespace WindowsFormsExamples
{
public partial class OnlyOneThread : Form
{
List<ManualResetEvent> threadStopEvents; //This will hold stop events for running threads
public OnlyOneThread()
{
InitializeComponent();
threadStopEvents = new List<ManualResetEvent>();
}
private void runThreadBtn_Click(object sender, EventArgs e)
{
ManualResetEvent evt = new ManualResetEvent(false);
ParameterizedThreadStart ts = new ParameterizedThreadStart(this.ThreadFunc);
Thread t = new Thread(ts);
t.Start(evt);
}
private delegate void UptadeThreadCountDelegate(); //This delegate is used by Invoke method
private void UpdateThreadCount()
{
threadcountLbl.Text = threadStopEvents.Count.ToString();
}
protected override void OnClosed(EventArgs e)
{
base.OnClosed(e);
//We must stop threads if they are still running
lock (threadStopEvents) // locking prevents simultaneous list access
{
foreach (ManualResetEvent evt in threadStopEvents)
{
evt.Set(); //signal all events
}
}
}
//This is thread function
private void ThreadFunc(Object obj)
{
ManualResetEvent stopEvent = obj as ManualResetEvent; //cast an object that was passed by Thread.Start()
lock (threadStopEvents) // locking prevents simultaneous list access
{
foreach (ManualResetEvent evt in threadStopEvents)
{
evt.Set(); //signal all events for all other threads to stop
}
threadStopEvents.Add(stopEvent); //Put our event on list
}
if (this.IsHandleCreated) // This is necessary for invocation
this.Invoke(new UptadeThreadCountDelegate(this.UpdateThreadCount)); //Invoke counter update
for (int i = 0; i < 60; i++) // this will run about 1 minute
{
if (stopEvent.WaitOne(0)) // Tests stopEvent and continues
{
//Stop signaled!!! exit!
break;
}
Thread.Sleep(1000); //Sleep 1 second
}
lock (threadStopEvents) // locking prevents simultaneous list access
{
threadStopEvents.Remove(stopEvent); //remove stop event from list
}
if (this.IsHandleCreated) // This is necessary for invocation
this.Invoke(new UptadeThreadCountDelegate(this.UpdateThreadCount)); //Invoke counter update
}
}
}
If you want to run this example you must create WindowsForms project and add Button and label on the form, then use this code to bind to those controls. Note an invocation of forms method. This is necessary when don from non-GUI threads.
I can not see an easy solution to this problem... Multithreading is never easy. Personally, I would propose following (a sort of deviation of the producer/consumer situation):
First have a general counter which signifies the currently to be rendered image (can be a simple int which is incremented for each button pressed)
An ImageMonitor which is nicely locked and has a methods to:
add an image to be rendered (with the current counter) -> this happens for each button pressed
retrieve the image which should be rendered (including the counter of the image)
Process a rendered image
Now we need a continously working Background thread which loops and in every iteration checks the ImageMonitor for the newest image to process, processes the image and returns it back to the ImageMonitor (including the counter)
When the ImageMonitor gets a rendered image from the background renderer, then it can check if the image has the correct counter value, if so then it can swap the current image with the rendered image
This solution is obviously a little complicated. However, it should work. I'm interested in other (easier) solutions.
Good luck
In my app, I have a thread that runs continuously. By using Thread.Sleep(), the function executes every 10 minutes.
I need to be able to kill this thread when a user clicks a button. I know Thread.Abort() is not reliable. I can use a variable to stop the thread, but since it is sleeping it could be another 10 minutes before the thread kills itself.
Any ideas?
Why don't you use a timer to schedule the task every ten minutes instead. That will run your code on a thread pool thread and thus you will not have to manage this yourself.
For more details see the System.Threading.Timer class.
Instead of Thread.Sleep use a System.Threading.ManualResetEvent. The WaitOne method has a timeout just like Thread.Sleep, your thread will sleep for that interval unless the event is triggered first, and the return value tells you whether the interval elapsed or the event was set.
So here's a sample that users timers to do the work as suggested by Brian. Use start/stop as needed. To cleanup the (Program) object once you are done with it make sure you call Dispose.
Just note that when you call Stop it will prevent the timer from firing again, however you still may have a worker thread in the middle of executing the timer_Elapsed handler, i.e. stopping the timer doesn't stop any currently executing worker thread.
using System;
using System.Timers;
namespace TimerApp
{
class Program : IDisposable
{
private Timer timer;
public Program()
{
this.timer = new Timer();
this.timer.Elapsed += new ElapsedEventHandler(timer_Elapsed);
this.timer.AutoReset = true;
this.timer.Interval = TimeSpan.FromMinutes(10).TotalMilliseconds;
}
void timer_Elapsed(object sender, ElapsedEventArgs e)
{
// TODO...your periodic processing, executed in a worker thread.
}
static void Main(string[] args)
{
// TODO...your app logic.
}
public void Start()
{
this.timer.Start();
}
public void Stop()
{
this.timer.Stop();
}
public void Dispose()
{
this.timer.Dispose();
}
}
}
Building on Ben's answer, here's the pattern to help you out...
using System.Threading;
public class MyWorker {
private ManualResetEvent mResetEvent = new ManualResetEvent(false);
private volatile bool mIsAlive;
private const int mTimeout = 6000000;
public void Start()
{
if (mIsAlive == false)
{
mIsAlive = true;
Thread thread = new Thread(new ThreadStart(RunThread));
thread.Start();
}
}
public void Stop()
{
mIsAlive = false;
mResetEvent.Set();
}
public void RunThread()
{
while(mIsAlive)
{
//Reset the event -we may be restarting the thread.
mResetEvent.Reset();
DoWork();
//The thread will block on this until either the timeout
//expires or the reset event is signaled.
if (mResetEvent.WaitOne(mTimeout))
{
mIsAlive = false; // Exit the loop.
}
}
}
public void DoWork()
{
//...
} }
One possibility is to not have it sleep for ten minutes. Have it sleep for 10 seconds then only do its work on every sixtieth wakeup. Then you only have a latency of ten seconds before it stops.
Aside: This is not necessarily the best solution but it's probably the quickest to implement. As with all possibilities you should do a cost/benefit analysis when selecting which solution is right for you.
If ten seconds is still too much, you can drop it further although keep in mind that dropping it too far will result in a possible performance impact.
You're right that you shouldn't kill threads from outside, it's usually a recipe for disaster if you happen to do it while they have a lock on some resource that's not freed on kill. Threads should always be responsible for their own resources, including their lifetimes.
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();
}
}