8

I'm using .Net 4 to build a simple windows service , the problem happens when I want to make a 5 min delay before starting the service.

protected override void OnStart(string[] args)
{
    // make a 5 min delay
    // do something
}

but after few seconds the service stops and gives me a time out error (saw this in the event-log). what am I suppose to do?

Malachi
  • 3,205
  • 4
  • 29
  • 46
Ehsan Zargar Ershadi
  • 24,115
  • 17
  • 65
  • 95

8 Answers8

7

Start your long running process in a new thread, so don't block the OnStart method. example:

using System.Threading;

protected override void OnStart(string[] args)
{
    ThreadPool.QueueUserWorkItem(new WaitCallback((_) =>
    {
        Thread.Sleep(5 * 1000 * 60);//simulate 5 minutes work

       // do something
    }));
}
Jalal Said
  • 15,906
  • 7
  • 45
  • 68
  • 1
    Yes. Good idea. Ignore windows delayed service start options from the operating system, then handcode around them. – TomTom Aug 10 '11 at 11:25
  • @TomTom: `Yes. Good idea. Ignore windows delayed service start options from the operating system, then handcode around them.` why the -1 then? do you make it by mistake?? – Jalal Said Aug 10 '11 at 11:29
  • 2
    TomTom are you sour all versions of windows supports delayed service options , because I'm using windows 2003. – Ehsan Zargar Ershadi Aug 10 '11 at 11:38
  • No, only the ones that are current. 2003 is quite end of life. – TomTom Aug 10 '11 at 11:41
  • 1
    @TomTom: 2003 is still in extended support for 4 more years. We don't always get to pick what we use, or what our customers use. – Joe Aug 10 '11 at 11:47
  • @Incognito: I am confused by your comment, the `OnStart must return as fast as possible` that is exactly what I am doing here. I start immediate thread and wrap the whole work inside it, so the `OnStart` will return instantly. – Jalal Said Aug 10 '11 at 12:12
3

Dont. Services have to start when asked for. OnStart HAS TO RETURN. FAST.

That said, the service then can wait 5 minutes until it DOES something, but you can not just stop the startup cycle.

Start it, then have the worker thread wait until it does something.

That said, there is a configuration entry that allows a service to be started with a delay. It is configured FOR the service, much like Manual, Automatic there is a delayed entry. This makes sure the service only starts when the machine has had a little time to settle down from starting. This may be better/good enough.

Malachi
  • 3,205
  • 4
  • 29
  • 46
TomTom
  • 61,059
  • 10
  • 88
  • 148
  • can you explain more about the configuration entry? please. – Ehsan Zargar Ershadi Aug 10 '11 at 11:19
  • Open a windows service configuration, look at the options, use google. Not that hard, come on. Let me do it. Google "Windows Service Startup Delayed", second entry is... http://www.techrepublic.com/blog/datacenter/delayed-start-feature-increases-options-for-windows-services/1552 – TomTom Aug 10 '11 at 11:21
  • @TomTom It would be good solution, but it is supported only on Win7, Vista and 2008 server ... – Incognito Aug 10 '11 at 12:34
2

The OnStart method needs to return in a timely fashion otherwise you will get a time out error.

What you need to do is start a thread from OnStart and in that thread wait 5 minutes before actually starting your service. So your OnStart method becomes:

serviceThread = new Thread(new ThreadStart(workerClass.WorkerMethod));

serviceThread.Start();

And WorkerClass.WorkerMethod does the actual starting of the service.

ChrisF
  • 134,786
  • 31
  • 255
  • 325
1

A service has to respond when it's told to start, or Windows thinks its malfunctioning. So you have two options:

  1. Write a seperate application that runs on startup, waits 5 minutes, and then starts the service.

  2. Start the service, and put a five minute delay in it before it starts doing whatever it's business logic is. So long as Windows thinks it started up normally, it's happy.

Something like this:

private static Timer t;
protected override void OnStart(string[] args)
{
    t = new Timer(5000*60);
    t.Elapsed += new ElapsedEventHandler(OnTimedEvent)
    t.Start()
}

private static void OnTimedEvent(object source, ElapsedEventArgs e)
{
    // real code here
}
Tridus
  • 5,021
  • 1
  • 19
  • 19
1

I don't understand why you want to delay your service start routine for 5 mins. if the service routine takes longer Service Control Manager probably aborts all the operation so your service can not start. You would rather need to start a thread/Timer inside OnStart Method and Wait for 5 mins on the Thread/Timer procedure.

protected override void OnStart(string[] args)
        {              
            Thread processor= new Thread(ThreadProc);
            processor.Start();
        }

        private void ThreadProc()
        {
            while (true)
            {
                Thread.Sleep(TimeSpan.FromMinutes(5));

            }
        }
crypted
  • 10,118
  • 3
  • 39
  • 52
1

Use a System.Timers.Timer to defer your actions... Here's some code from one of my services. The reason I use the defer is because windows assumes a service is broken if it takes too long to return from the onstart event. Since I do a lot of stuff when the service first starts I start the service very quickly with just the creation of a timer and then let that event deal with the real startup stuff.

    protected override void OnStart(string[] args)
    {
        try
        {
            // Using a timer Event to start asynchronously
            StartupTimer = new Timer();
            StartupTimer.Elapsed += StartupTimer_Elapsed;
            StartupTimer.AutoReset = false;
            StartupTimer.Interval = 5*60*1000;
            StartupTimer.Start();
        }
        catch (Exception ex)
        {
            LogMessage(true, ex.ToString());
        }
    }

    private void StartupTimer_Elapsed(object sender, ElapsedEventArgs e)
    {
        try
        {
            RunSetup(true);
        }
        catch (Exception ex)
        {
            LogMessage(true, ex.ToString());
        }
    }
Chris
  • 27,210
  • 6
  • 71
  • 92
0

A straight forward way is to use System.Threading.Timer and set it's due time to 5 minutes, please see System.Threading.Timer for more information.

Andreas Ågren
  • 3,879
  • 24
  • 33
0

The root of the problem is that if the service takes along time to start Windows will think that it is malfunctioning and kill it.

You can fix this by first telling Windows that this service is going to take some time to start.

To do this see the answers of this SO question: windows service startup timeout

Community
  • 1
  • 1
Shiraz Bhaiji
  • 64,065
  • 34
  • 143
  • 252