20

I have a windows service where in I want to create a file every 10 seconds.

I got many reviews that Timer in Windows service would be the best option.

How can I achieve this?

Parth Bhatt
  • 19,381
  • 28
  • 133
  • 216
  • I would not recommend using any timer in a windows service, as improperly exceptions can cause the timer to stop, but not the service. Its an easy thing to forget the right exception handling. – StingyJack Sep 30 '15 at 13:52
  • ...improperly _handled or unhandled_ exceptions.. – StingyJack Oct 28 '17 at 20:12

6 Answers6

30

Firstly, pick the right kind of timer. You want either System.Timers.Timer or System.Threading.Timer - don't use one associated with a UI framework (e.g. System.Windows.Forms.Timer or DispatcherTimer).

Timers are generally simple

  1. set the tick interval
  2. Add a handler to the Elapsed event (or pass it a callback on construction),
  3. Start the timer if necessary (different classes work differently)

and all will be well.

Samples:

// System.Threading.Timer sample
using System;
using System.Threading;

class Test
{
    static void Main() 
    {
        TimerCallback callback = PerformTimerOperation;
        Timer timer = new Timer(callback);
        timer.Change(TimeSpan.Zero, TimeSpan.FromSeconds(1));
        // Let the timer run for 10 seconds before the main
        // thread exits and the process terminates
        Thread.Sleep(10000);
    }

    static void PerformTimerOperation(object state)
    {
        Console.WriteLine("Timer ticked...");
    }
}

// System.Timers.Timer example
using System;
using System.Threading;
using System.Timers;
// Disambiguate the meaning of "Timer"
using Timer = System.Timers.Timer;

class Test
{
    static void Main() 
    {
        Timer timer = new Timer();
        timer.Elapsed += PerformTimerOperation;
        timer.Interval = TimeSpan.FromSeconds(1).TotalMilliseconds;
        timer.Start();
        // Let the timer run for 10 seconds before the main
        // thread exits and the process terminates
        Thread.Sleep(10000);
    }

    static void PerformTimerOperation(object sender,
                                      ElapsedEventArgs e)
    {
        Console.WriteLine("Timer ticked...");
    }
}

I have a bit more information on this page, although I haven't updated that for a long time.

jgauffin
  • 99,844
  • 45
  • 235
  • 372
Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • Hey Thanks Jon Skeet..!! Can you please tell me where exactly I can see the output of my `Console.WriteLine("");`? I am a newbie. – Parth Bhatt Mar 31 '11 at 06:15
  • 1
    @PARTH: Well these are sample console applications - I just compiled and ran them on the command line. They're only meant to demonstrate how to set up and start a timer. You wouldn't usually use Console.WriteLine in a Windows Service. There are lots of tutorials around on the general aspects of writing a Windows Service - I was just focusing on the specific task of starting a timer. – Jon Skeet Mar 31 '11 at 06:17
  • Hey Jon This works for 10 seconds only But I want that it should keep on doing this 24 x 7 then it that case what can be the modifications? – Parth Bhatt Mar 31 '11 at 06:31
  • @PARTH: In a Windows Service, you would start the timer from the "Start" event or whatever. This finishes after 10 seconds because the main thread exits. That doesn't happen in a Windows Service. I suggest you read up on the lifecycle of a Windows Service for more information. – Jon Skeet Mar 31 '11 at 06:35
  • So if I am not wrong, you mean to say `Thread.Sleep(10000)` will not be required in Windows Service? – Parth Bhatt Mar 31 '11 at 06:39
  • @PARTH: Exactly. It's just for the purposes of the sample. – Jon Skeet Mar 31 '11 at 06:41
  • Thanks Jon for all your help :). Yeah then it is fine. Rest of the code I suppose would remain the same. Am I right? Also is `timer.AutoReset = true;` is not required in windows Service, right? – Parth Bhatt Mar 31 '11 at 06:43
  • @PARTH: You want it to be true by the sounds of it, but the default is already true. – Jon Skeet Mar 31 '11 at 06:47
  • Ok it is working in console application but when I try to put the same code in WindowsService on the `OnStart()` event then it does not call the `PerformTimerOperation` method. In windows service I am creating a new file under 'PerformTimerOperation`. – Parth Bhatt Mar 31 '11 at 06:51
  • @PARTH: Are you sure that it's not *trying* to create the file, but failing due to permissions? Try just writing to the event log, or something else that you'll be able to use for diagnostic purposes. – Jon Skeet Mar 31 '11 at 06:56
  • 1
    Hey Jon, Thanks for the reply. This did work for me.Thanks "Master at Work"(Jon Skeet)..!! Thanks a lot :) – Parth Bhatt Mar 31 '11 at 09:52
13

I would not recommend System.Timers.Timer since it silently eats unhandled exceptions and therefore hides errors that you should fix. imho better that your code blows up in your face if you do not handle exceptions properly.

As for System.Threading.Timer I tend to use the Change method to start/stop the timer in a pattern like this:

public class MyCoolService
{
    Timer _timer;

    public MyCoolService()
    {
        _timer = new Timer(MyWorkerMethod, Timeout.Infinite, Timeout.Infinite);
    }

    protected void OnStart()
    {
        _timer.Change(15000, Timeout.Infinte);
    }

    protected void MyWorkerMethod()
    {
        //pause timer during processing so it
        // wont be run twice if the processing takes longer
        // than the interval for some reason
        _timer.Change(Timeout.Infinite, Timeout.Infinite); 

        try
        {
            DoSomeWork();
        }
        catch (Exception err)
        {
            // report the error to your manager if you dare
        }

        // launch again in 15 seconds
        _timer.Change(15000, Timeout.Infinite);
    }

}
jgauffin
  • 99,844
  • 45
  • 235
  • 372
3

This is how you do it simply

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.ServiceProcess;
using System.Text;
using System.Timers;
using System.IO;

  namespace MyService
{
    public partial class Service1 : ServiceBase
    {
        Timer myTimer;
        int x = 0;
        public Service1()
         {
             InitializeComponent();
         }

         protected override void OnStart(string[] args)
         {

             myTimer = new Timer(10000);                                // Sets a 10 second interval
             myTimer.Elapsed +=new ElapsedEventHandler(myTimer_Elapsed);// Specifies The Event Handler
             myTimer.Enabled = true;                                    // Enables the control
             myTimer.AutoReset = true;                                  // makes it repeat
             myTimer.Start();                                           // Starts the interval




         }
         protected void myTimer_Elapsed(object sender, ElapsedEventArgs e)
         {
             // All the Cool code that you need to run eg. Making a new file every 10 seconds
             x++;
             StreamWriter myFile = new StreamWriter("MyFile" + x.ToString() + ".txt");
             myFile.Write("Something");
             myFile.Close();
         }
         protected override void OnStop()
         {
         }
     }
 }

The Code above is the whole service with the timer. I realize this is an old post but it took me hours to figure this out. Hopefully it helps someone out there.

iuppiter
  • 315
  • 3
  • 9
1

This should just be a case of firing up a System.Timers.Timer with the right Interval (and AutoReset set to true), and handling Elapsed (but watch out; the callback is not on any particular thread).

MSDN has an example: http://msdn.microsoft.com/en-us/library/system.timers.timer.elapsed.aspx

also from MSDN:

The Timer component is a server-based timer, which allows you to specify a recurring interval at which the Elapsed event is raised in your application. You can then handle this event to provide regular processing. For example, suppose you have a critical server that must be kept running 24 hours a day, 7 days a week. You could create a service that uses a Timer to periodically check the server and ensure that the system is up and running. If the system is not responding, the service could attempt to restart the server or notify an administrator.

The server-based Timer is designed for use with worker threads in a multithreaded environment. Server timers can move among threads to handle the raised Elapsed event, resulting in more accuracy than Windows timers in raising the event on time.

Community
  • 1
  • 1
Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
1

Here you have example how to use Timer in Windows Service.

Paweł Smejda
  • 1,879
  • 1
  • 17
  • 25
0

fully tested solution...

 using System;
    using System.Configuration;
    using System.ServiceProcess;
    using System.Timers;

    namespace SomeServices.WindowsService
    {
        public partial class SomeServicesWindowsService : ServiceBase 
        {
            private const int DefaultTriggerInterval = 5000;

            private readonly Timer _trigger;

            public SomeServicesWindowsService ()
            {
                InitializeComponent();
                _trigger = new Timer(GetTriggerInterval());
                _trigger.Elapsed += TriggerElapsed;
            }
            public bool ContinueTriggering { get; set; }

            public void TriggerElapsed(object sender, ElapsedEventArgs e)
            {
                var subject = (Timer)sender;
                subject.Stop();

                using (var service = new DeliveryServiceManager())
                {
                    service.ShouldContinue += service_ShouldContinue;
                    service.Run();
                }

                if (ContinueTriggering)
                    subject.Start();
            }

            void service_ShouldContinue(object sender, ShouldContinueEventArgs e)
            {
                e.Continue = ContinueTriggering;
            }

            public double GetTriggerInterval()
            {
                int interval;
                return int.TryParse(ConfigurationManager.AppSettings["triggerInterval"], out interval)
                    ? interval
                    : DefaultTriggerInterval;
            }

            protected override void OnStart(string[] args)
            {
                ContinueTriggering = true;
                _trigger.Start();
            }

            protected override void OnStop()
            {
                ContinueTriggering = false;
                _trigger.Stop();
            }
        }

        public class DeliveryServiceManager : IDisposable
        {
            public event EventHandler<ShouldContinueEventArgs> ShouldContinue;
            protected virtual void OnShouldContinue(ShouldContinueEventArgs e)
            {
                var handler = ShouldContinue;
                if (handler != null)
                {
                    handler(this, e);
                }
            }

            public void Dispose()
            {
                ShouldContinue = null;
            }

            public void Run()
            {
               //Iterate Something here.
                var eventArgs = new ShouldContinueEventArgs{Continue =  false};
                OnShouldContinue(eventArgs);
                if (!eventArgs.Continue)
                {
                    //Run step();        
                }
            }
        }

        public class ShouldContinueEventArgs : EventArgs
        {
            public bool Continue { get; set; }
        }
    }
Nuri YILMAZ
  • 4,291
  • 5
  • 37
  • 43