Embedd_0913
Embedd_0913

Reputation: 16565

Timer tick event is not called in windows service

I have a window service which plays a sound file at a specified time, so to do that I have taken Timer but it's Tick event is never fired, same is working in WinForm application.

Below is the code snippet of my service...

public partial class ClockService : ServiceBase
{
    private TimeSpan _alarmTime = new TimeSpan(9, 55, 0);
    private int _snoozeTime = 2; // 2 minutes
    private int _repeatCounter = -1;
    private const int ALARM_REPETITION = 5;
    private string _alarmSoundPath = @"C:\Sound\default.wav";
    private string _alarmLogPath = @"C:\Sound\log.txt";

    public ClockService()
    {
        InitializeComponent();
        alarmTimer.Enabled = true;
    }

    protected override void OnStart(string[] args)
    {
        using (FileStream fileStream = new FileStream(_alarmLogPath, FileMode.OpenOrCreate))
        {
            using (StreamWriter writer = new StreamWriter(fileStream))
            {
                writer.WriteLine("Service has started at {0}", DateTime.Now);
            }
        }
    }

    protected override void OnStop()
    {
        using (FileStream fileStream = new FileStream(_alarmLogPath, FileMode.OpenOrCreate))
        {
            using (StreamWriter writer = new StreamWriter(fileStream))
            {
                writer.WriteLine("Service has stopped at {0}", DateTime.Now);
            }
        }
    }

    private void alarmTimer_Tick(object sender, EventArgs e)
    {
        using (FileStream fileStream = new FileStream(_alarmLogPath, FileMode.OpenOrCreate))
        {
            using (StreamWriter writer = new StreamWriter(fileStream))
            {
                writer.WriteLine("Alarm time is: {0}", _alarmTime);
            }
        }

        TimeSpan currentTime = new TimeSpan(DateTime.Now.TimeOfDay.Hours, DateTime.Now.TimeOfDay.Minutes, DateTime.Now.TimeOfDay.Seconds);


        if (currentTime == _alarmTime)
        {
            using (FileStream fileStream = new FileStream(_alarmLogPath, FileMode.OpenOrCreate))
            {
                using (StreamWriter writer = new StreamWriter(fileStream))
                {
                    writer.WriteLine("Alarm time is: {0} and current time is: {1}", _alarmTime, currentTime);
                }
            }

            _alarmTime = _alarmTime.Add(new TimeSpan(0, _snoozeTime, 0));
            _repeatCounter++;

            if (File.Exists(_alarmSoundPath))
            {
                SoundPlayer player = new SoundPlayer(_alarmSoundPath);
                player.PlayLooping();
            }

        }

        if (_repeatCounter == ALARM_REPETITION)
        {
            _alarmTime = _alarmTime.Subtract(new TimeSpan(0, (ALARM_REPETITION * _snoozeTime), 0));
            _repeatCounter = 0;
        }

    }
}

To make sure that I have done everything properly, here is my InitializeComponent method

    private void InitializeComponent()
            {
                this.components = new System.ComponentModel.Container();
                this.alarmTimer = new System.Windows.Forms.Timer(this.components);
                this.alarmTimer.Enabled = true;
                this.alarmTimer.Interval = 1000; 
            this.alarmTimer.Tick += new System.EventHandler(this.alarmTimer_Tick);
        this.ServiceName = "PravoAlarmService";
    }

Please anyone have a look and guide me...problem is the tick event is never fired..

Upvotes: 4

Views: 9066

Answers (5)

Doobi
Doobi

Reputation: 4842

Are you sure it's the timer that's the issue? It's extremely unusual for a windows service to access the sound system, (How would you turn it off?) it may be blocked or it may require "interaction with desktop" enabled.

Having said that, TomTom is right, Forms Timers are about being able to Marshal to the UI thread, which you don't have, rather using a Threading timer.

Upvotes: 0

Arseny
Arseny

Reputation: 7361

try to use other Timer :) here is difference

Upvotes: 0

kerrubin
kerrubin

Reputation: 1616

I think System.Timers.Timer is a better choice :

Timer _timer = new Timer();
// In miliseconds 60000 = 1 minute
// This timer will tick every 1 minute
_timer.Interval += 6000;
// Activate the timer
_timer.Enabled = true;
// When timer "tick"
_timer.Elapsed += new ElapsedEventHandler(_timer_Elapsed);

Upvotes: 1

TomTom
TomTom

Reputation: 62157

Dont use a System.Windows.FOrms.Timer, use a System.Threading.Timer.

A service is not a form.

Upvotes: 0

marc_s
marc_s

Reputation: 755321

Try to use the System.Timers.Timer instead.

this.alarmTimer = new System.Timers.Timer();

The System.Windows.Forms.Timer - as it names implies - works in Forms applications, but not in something like a NT Service.

Upvotes: 11

Related Questions