How to run a task when a windows service starts?
Asked Answered
F

3

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?

Flee answered 12/4, 2013 at 14:12 Comment(0)
B
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);
Bentz answered 12/4, 2013 at 14:16 Comment(3)
The waiting is not waiting as such. I mean it will just captures any exceptions from that task.Flee
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.Breezy
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.Bentz
P
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);
    }
}
Putup answered 12/4, 2013 at 14:17 Comment(3)
your catch never catches. It can catch only when you wait on it.Flee
@TheLight: It should only catch exceptions from Task.Factory.StartNew, not from StartPolling. You are starting a service to run async, not to wait for it to finish. Updated the answer.Putup
Task.Factory.StartNew doesn't return exception. You can capture the exception when waiting on a task. or is there any other way?Flee
M
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.

Madder answered 12/4, 2013 at 14:14 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.