TopShelf Service Timer ElapsedEventHandler does not seem to fire

453 views
Skip to first unread message

Babu Mannaravalappil

unread,
Aug 16, 2018, 9:38:15 AM8/16/18
to topshelf-discuss
Hi,

This is the copy of a help request I posted on Stack Overflow but did not get any in the past 4 days.  So, hoping someone here can help.

I have a .NET Console application using TopShelf to run this app as a windows service. The Console application itself has no problem running and doing what it is supposed to do. I have TopShelf nuget package installed and have configured the TopShelf correctly (to my knowledge).


When I debug the application or even after I installed the application into Windows service and started the service, it does not seem to execute the method "DoUpdate" I have defined the timer to be executed in the elapsed event. But it is not happening. Any clue anyone?


Here is my Main method in the Console Application:

public static void Main()
    {
        try
        {
            HostFactory.Run(x =>
           {
               x.Service<DNSUpdateTopShelf>(a =>
              {
                  a.ConstructUsing(n => new DNSUpdateTopShelf());
                  a.WhenStarted(ts => ts.Start());
                  a.WhenStopped(ts => ts.Stop());
              });
               x.SetDescription("Update GoDaddy DNS Records");
               x.SetDisplayName("GoDaddy DNS Updater");
               x.SetServiceName("GoDaddyDNSUpdate");
               //x.RunAsNetworkService();
               x.RunAsLocalSystem();
               x.StartAutomatically();
           });
        }
        catch (Exception e)
        {
            System.Console.WriteLine(e.Message);
        }
        System.Console.WriteLine("---------------");
        System.Console.ReadKey();
    }


Here is the class that does the work:

public class DNSUpdateTopShelf
{
    private System.Timers.Timer updateTimer;
    private int interval;
    private EventLog log;

    public DNSUpdateTopShelf()
    {
        Initialize();
    }

    public void Initialize()
    {
        //log = new EventLog("DynaProLogs");
        updateTimer = new System.Timers.Timer();
    }

    public void Start()
    {
        try
        {
            Utils.WriteLog("In Start Method");

            var jsonFile = $"{Directory.GetCurrentDirectory()}\\appconfig.json";

            using (StreamReader r = new StreamReader(jsonFile))
            {
                var json = r.ReadToEndAsync().Result;
                var config = (JObject)JsonConvert.DeserializeObject(json);
                interval = config["interval"].Value<int>();
            }

            updateTimer.Interval = interval;
            updateTimer.Elapsed += new ElapsedEventHandler(DoUpdate);
        }
        catch (Exception ex)
        {
            Utils.WriteLog($"DNSUpdater - {ex.Message}", type: EventLogEntryType.Error);
            throw;
        }
    }

    public void Stop()
    {
        Utils.WriteLog("In Stop Method");
        updateTimer.Stop();
    }

    public void DoUpdate(object sender, ElapsedEventArgs e)
    {
        Utils.WriteLog("In DoUpdate method");

        DNSUpdater updater = new DNSUpdater();

        var results = Task.Run( async () => await updater.UpdateAllDomainIPAsync()).Result;
        //var results = updater.UpdateAllDomainIPAsync().Result;

        foreach (UpdateResult result in results)
        {
            Utils.WriteLog($"{result.RequestURI} -- {result.Message}");
        }
    }
}


The problem is: The DoWork method does not get called ever. I have changed the ElapsedTime of the timer to many different duration. But it never seems to get called at all.


I can confirm that the "Interval" property of the timer object does get set. I can also confirm that this service gets installed in Windows Service and is running. As I said, I tried to test it both by debugging the whole application including TopShelf as well as after building and installing it as a service. I can't figure out why the timer elapsed event handler (DoUpdate) is not firing.


Babu.

Chris Patterson

unread,
Aug 21, 2018, 6:03:28 PM8/21/18
to topshelf...@googlegroups.com
Pretty sure you need to use a System.Threading.Timer, instead of a System.Timers.Timer.

The first works with proper threads, the latter only works with a UI application.


--
You received this message because you are subscribed to the Google Groups "topshelf-discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to topshelf-discuss+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

ric...@wizardhat.co.uk

unread,
Aug 21, 2018, 6:54:22 PM8/21/18
to topshelf...@googlegroups.com
Both System.Timers.Timer and System.Threading.Timer are intended for multi-threaded applications. The former uses the latter under the hood.

You do need to either set Enabled to true or call Start() on a System.Timers.Timer though.
I think that a System.Threading.Timer starts automatically, which you might find a bit more intuitive.
To unsubscribe from this group and stop receiving emails from it, send an email to topshelf-discu...@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

 

--
You received this message because you are subscribed to the Google Groups "topshelf-discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to topshelf-discu...@googlegroups.com.
Reply all
Reply to author
Forward
0 new messages