当Windows服务启动时如何运行任务?

7

我有一个Windows服务,我已经编写了代码,在OnStart()事件中运行任务:

 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);
            }           
        }

DoTask是一个无限循环。只有当服务停止时,它才会停止。

但是当我尝试启动服务时,它会等待很长时间,然后给出以下错误:

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.

如何解决这个问题?
3个回答

8

为什么你要等待任务完成呢?

我认为 Task.Wait 阻塞了当前线程,因此在启动服务时会超时。

编辑:您需要移除这个阻塞:

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

Task.Wait确实会阻塞当前线程。根据MSDN的说明:

Task.Wait方法

等待任务完成执行。

编辑2,请改用以下方法

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);

等待并不是真正的等待。我的意思是它只会捕获该任务中的任何异常。 - The Light
等待是“等待本身”。你的代码停在那里,什么也不做,等待任务完成。而且它正在同一个调用OnStart的线程上等待。 - Damien_The_Unbeliever
1
检查我的编辑,使用任务继续来完成。在服务启动期间不能检查异常,因为这个过程需要时间,很可能会超时。 - Conrad Clark

2

我猜这是因为你在等待OriginalFileProcessor.StartPolling()结束,但这永远不会发生。你应该把你的任务实例移到一个单独的成员中,而不是等待它完成:

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);
    }
}

你的异常捕捉永远不会捕捉到。只有在你等待它时,才能捕捉到异常。 - The Light
@TheLight:它只应该从Task.Factory.StartNew中捕获异常,而不是从StartPolling中捕获。您正在启动一个异步运行的服务,而不是等待它完成。已更新答案。 - Carsten
Task.Factory.StartNew不会返回异常。当等待任务时,您可以捕获异常。还有其他方法吗? - The Light

1

在循环中,您需要检查服务状态是否为“停止”,并退出循环。在操作系统决定终止您之前,您有5秒钟的时间。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接