简体   繁体   English

在Windows服务中运行长时间运行的任务

[英]Running a long-running Task within a Windows Service

I have written a Windows Service project which hosts a long-running message pump task which is meant to run for the duration of the service. 我编写了一个Windows服务项目,它承载了一个长期运行的消息泵任务,该任务是在服务期间运行的。 When the service starts, it starts the task. 服务启动时,它会启动任务。 When the service stops, it stops the task: 当服务停止时,它会停止任务:

void OnStart()
{
    MessagePump.Start();
}

void OnStop()
{
    MessagePump.Stop();
}

Where MessagePump.Start does a Task.Factory.StartNew, and MessagePump.Stop signals the task to stop and does a Wait(). MessagePump.Start执行Task.Factory.StartNew,MessagePump.Stop指示任务停止并执行Wait()。

So far so good, but I'm wondering how best to handle faults. 到目前为止一切都那么好,但我想知道如何最好地处理故障。 If the task has an unhandled exception, I'd want the service to stop but since nothing is typically Wait-ing on the task, I imagine it'll just sit doing nothing. 如果任务有一个未处理的异常,我希望服务停止,但由于没有任何东西通常在等待任务,我想它只是无所事事。 How can I elegantly handle this situation? 我怎样才能优雅地处理这种情况?

UPDATE: 更新:

The consensus seems to be using 'await' or ContinueWith. 共识似乎是使用'await'或ContinueWith。 Here is how I'm currently coding my Start method to use this: 以下是我目前编写Start方法的方法来使用它:

public async static void Start()
{
    this.state = MessagePumpState.Running;
    this.task = Task.Factory.StartNew(() => this.ProcessLoop(), TaskCreationOptions.LongRunning);
    try
    {
        await this.task;
    }
    catch
    {
        this.state = MessagePumpState.Faulted;
        throw;
    }
}

Make you MessagePump.Start() method return the task. 让你MessagePump.Start()方法返回任务。 Then 然后

MessagePump.Start().ContinueWith(t => 
{
    // handle exception 
}, 
TaskContinuationOptions.OnlyOnFaulted);

UPDATE: I would do the next: 更新:我会做下一个:

private MessagePump _messagePump;

async void OnStart()
{
    this._messagePump = new MessagePump();
    try
    {
        // make Start method return the task to be able to handle bubbling exception here
        await _messagePump.Start();
    }
    catch (Exception ex)
    {
        // log exception
        // abort service
    }
}

void OnStop()
{
    _messagePump.Stop();
}

public enum MessagePumpState
{
    Running,
    Faulted
}

public class MessagePump
{
    private CancellationTokenSource _cancallationTokenSrc;
    private MessagePumpState _state;
    public async Task Start()
    {
        if (_cancallationTokenSrc != null)
        {
            throw new InvalidOperationException("Task is already running!");
        }

        this._state = MessagePumpState.Running;
        _cancallationTokenSrc = new CancellationTokenSource();
        var task = Task.Factory.StartNew(() => this.ProcessLoop(_cancallationTokenSrc.Token), _cancallationTokenSrc.Token);
        try
        {
            await task;
        }
        catch
        {
            this._state = MessagePumpState.Faulted;
            throw;
        }
    }

    public void Stop()
    {
        if (_cancallationTokenSrc != null)
        {
            _cancallationTokenSrc.Cancel();
            _cancallationTokenSrc = null;
        }
    }

    public void ProcessLoop(CancellationToken token)
    {
        // check if task has been canceled
        while (!token.IsCancellationRequested)
        {
            Console.WriteLine(DateTime.Now);
            Thread.Sleep(1000);
        }
    }
}

You can try something like this : 你可以尝试这样的事情:

void OnStart()
{
    MessagePump.StartAsync(); 
    MessagePump.ErrorEvent += OnError();
}

Then your StartAsync will look something like: 然后你的StartAsync看起来像:

public async Task StartAsync()
{
     // your process
     // if error, send event to messagePump
}

And if you decide to use Tasks, then it is better to use Task.Run and not Task.Factory.StartNew() 如果你决定使用Tasks,那么最好使用Task.Run而不是Task.Factory.StartNew()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Windows Service Application仅执行一次长时间运行的任务,并在完成后自行停止 - Windows Service Application to perform long-running task only once and stop itself after completion 从Windows服务处理长时间运行的操作 - Processing long-running operations from a windows service 关闭Windows服务中的长时间运行的进程 - Shutting down a Long-running process in a Windows Service Rx如何并行化长时间运行的任务? - Rx How to parallelize long-running task? 长期运行的后台任务中的Internet访问 - Internet access in a long-running background task 长期运行的WCF服务即将终止的原因是什么? - Reasons for long-running WCF service dying? 创建长期运行的工作流服务 - Creating a long-running Workflow Service 没有 IHostedService 运行应用程序的整个生命周期的长时间运行的任务? - Long-running task without IHostedService running the entire life of the application? 在长期运行的Windows服务中进行依赖注入-组合根源是正确的主意吗? - Dependency injection in long-running Windows service - Composition root the right idea? 在长时间运行的任务中显示自定义对话框窗口 - Displaying a custom dialog window during a long-running task
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM