-1

I have created a windows service on VS.net C#

In the OnStart event I start a timer.

In side the timer I call a function called DO()

the process of the DO() function is very long ( takes more than hour)

The process suppose to go this way

Start Then call the time immediately but due to the timer interval need to wait another day

protected override void OnStart(string[] args)
{
    eventLog1.WriteEntry("In OnStart.");

    try
    {
        Timer timer = new Timer();
        timer.Interval = 1000 * 60 *60 * 24;
        timer.Elapsed += new ElapsedEventHandler(this.OnTimer);
        timer.Start();
        DO();
    }
    catch (Exception ex)
    {
        eventLog1.WriteEntry("ERROR (OnStart) : " + ex.ToString());

    }
}

    public void OnTimer(object sender, ElapsedEventArgs args)
    {
        DO();
    }

    private void DO()
    {
     // Some process takes an hour
    }

When the service starts it stays an hour in "Starting"

Is there a way I can start my service DO() function immediatly once the service started but not from the OnStart event?

enter image description here

asmgx
  • 7,328
  • 15
  • 82
  • 143
  • Regarding Windows Services in general, when starting if your code takes too long Windows Service Manager marks your service as _unresponsive_. For this reason `OnStart()` and more importantly `Do()` should not carryout _"Some process takes an hour"_. `OnStart` should perform minimal work and spawn child threads as necessary. Also you should look into setting your Service State. https://learn.microsoft.com/en-us/windows/win32/services/service-status-transitions –  Feb 03 '21 at 03:24
  • yes, use a BackgroundWorker, eg. https://stackoverflow.com/questions/6481304/how-to-use-a-backgroundworker – Peter Henry Feb 03 '21 at 03:26
  • ...and to fix the _"Starting"_ problem, simply remove the call to `DO()` in your `OnStart` –  Feb 03 '21 at 03:28

1 Answers1

3

Presuming you left nothing out of your example, your timer elapsed method will run on the ThreadPool.

So I would change this line in OnStart

DO();

...with this line:

ThreadPool.QueueUserWorkItem(x => Do());

It has the same net effect of what would happen if the timer fired immediately and, more importantly, will not block on that line.

Zer0
  • 7,191
  • 1
  • 20
  • 34
  • Will the thread stop when I stop the service? – asmgx Feb 03 '21 at 03:40
  • 1
    @asmgx Yes, because thread pool threads are background threads. – Zer0 Feb 03 '21 at 03:42
  • 1
    @asmgx whenever a process exits all file handles and threads are closed –  Feb 03 '21 at 03:42
  • 1
    @MickyD No. Foreground threads will prevent a process from closing. See the [documentation](https://learn.microsoft.com/en-us/dotnet/api/system.threading.thread.isbackground?view=net-5.0#remarks). – Zer0 Feb 03 '21 at 03:44
  • @Zer0 I said when the _"process exits"_. If it is exiting, any prior foreground threads have already exited. Additionally a Windows Service has no primary thread by default –  Feb 03 '21 at 04:11
  • @MickyD You did and I agree. But if you try to stop a service with a foreground thread running it will not stop. A simple `new Thread()` will create a foreground thread, even in a service. Basically I wanted to clarify why this is safe, as opposed to spinning up your own `Thread`. I'm aware you can set `IsBackground` on a `Thread`, however we both know this is a common bug that prevents processes from exiting gracefully. – Zer0 Feb 03 '21 at 04:14
  • 1
    after experment, thread still running even after uninstalling the service – asmgx Feb 03 '21 at 04:48
  • @asmgx I would need to know the code in `DO`. I just tested that stopping a service with only background threads works fine. However, you're bringing up a different question entirely. Might need to find/ask a different question about stopping services. You can test anywhere in the code with `Thread.CurrentThread.IsBackground`. Anything that returns false can prevent the service from stopping. – Zer0 Feb 03 '21 at 05:08