7

I have a windows service and I've written the code to run the task within the OnStart() event:

 protected override void OnStart(string[] args)
        {
            this.DoTask();
        }

private void DoTask()
        {
            Task task1 = Task.Factory.StartNew(() => this.OriginalFileProcessor.StartPolling());

            try
            {
                Task.Wait(task1);
            }
            catch (Exception ex)
            {
                this.Log.Error("Failed running the task", ex);
            }           
        }

The DoTask is a never-ending loop. It will stop only when the service is stopped.

But when I try to start the service, it waits a long time then gives me the below error:

Windows could not start the ... service on Local Computer.
Error 1053: The service did not respond to the start or control request in a timely fashion.

How to resolve it?

The Light
  • 26,341
  • 62
  • 176
  • 258

3 Answers3

8

Why are you waiting your task to finish?

I think Task.Wait is blocking your current thread, then you're getting timeout while starting your service.

EDIT: You need to remove this block:

try
{
    Task.Wait(task1);
}
catch (Exception ex)
{
    this.Log.Error("Failed running the task", ex);
}  

Task.Wait is indeed blocking your current thread. According to MSDN:

Task.Wait Method

Waits for the Task to complete execution.

EDIT 2 Do this instead

Task task1 = Task.Factory.StartNew(() => this.OriginalFileProcessor.StartPolling()).ContinueWith( t =>
{
     var aggException = t.Exception.Flatten();
     foreach(var ex in aggException.InnerExceptions)
         this.Log.Error("Failed running the task", ex);
}, 
TaskContinuationOptions.OnlyOnFaulted);
Community
  • 1
  • 1
Conrad Clark
  • 4,533
  • 5
  • 45
  • 70
  • The waiting is not waiting as such. I mean it will just captures any exceptions from that task. – The Light Apr 12 '13 at 14:17
  • The waiting *is* "waiting as such". Your code is sat there, doing nothing, waiting for that task to complete. And it's doing that wait on the same thread that called `OnStart`. – Damien_The_Unbeliever Apr 12 '13 at 14:19
  • 1
    Check my edit, do it with a task continuation. You cannot check for exceptions during the service start, because as it seems this process takes time and it'll likely give you a timeout. – Conrad Clark Apr 12 '13 at 14:28
2

I guess this is, because you are waiting for the OriginalFileProcessor.StartPolling() to end, but this never happens. You should move your task instance into an seperate member and not wait for it to finish:

private Task m_task = null;

private void DoTask()
{
    try
    {
        m_task = Task.Factory.StartNew(() => this.StartPolling());
    }
    catch
    {
        this.Log.Error("Unable to start task", ex);
        throw;  // Rethrow, so that the OS knows, there was something wrong.
    }           
}

private void StartPolling()
{
    try
    {
        this.OriginalFileProcessor.StartPolling();
    }
    catch (Exception ex)
    {
        this.Log.Error("Failed running the task", ex);
    }
}
Carsten
  • 11,287
  • 7
  • 39
  • 62
  • your catch never catches. It can catch only when you wait on it. – The Light Apr 12 '13 at 14:19
  • @TheLight: It should only catch exceptions from [`Task.Factory.StartNew`](http://msdn.microsoft.com/en-us/library/dd321439.aspx), not from `StartPolling`. You are starting a service to run async, not to wait for it to finish. Updated the answer. – Carsten Apr 12 '13 at 14:22
  • Task.Factory.StartNew doesn't return exception. You can capture the exception when waiting on a task. or is there any other way? – The Light Apr 12 '13 at 14:31
1

In the loop you need to check if the service status is "stopping" and exit the loop. You have 5 seconds to do that before the OS decides to kill you.

Z .
  • 12,657
  • 1
  • 31
  • 56