c# - Windows 服务内的 TPL

标签 c# windows-services task-parallel-library

我需要在我正在并行编写的 Windows 服务中执行一些任务。我正在使用 VS2013、.NET 4.5 和这个线程 Basic design pattern for using TPL inside windows service for C#表明 TPL 是一条出路。

下面是我的实现。我想知道是否有人可以告诉我我是否做得正确!

public partial class FtpLink : ServiceBase
{
    private readonly CancellationTokenSource _cancellationTokenSource = new CancellationTokenSource();
    private readonly ManualResetEvent _runCompleteEvent = new ManualResetEvent(false);

    public FtpLink()
    {
        InitializeComponent();

        // Load configuration
        WebEnvironment.Instance.Initialise();
    }

    protected override void OnStart(string[] args)
    {
        Trace.TraceInformation("DatabaseToFtp is running");

        try
        {
            RunAsync(_cancellationTokenSource.Token).Wait();
        }
        finally
        {
            _runCompleteEvent.Set();
        }
    }

    protected override void OnStop()
    {
        Trace.TraceInformation("DatabaseToFtp is stopping");

        _cancellationTokenSource.Cancel();
        _runCompleteEvent.WaitOne();

        Trace.TraceInformation("DatabaseToFtp has stopped");
    }

    private async Task RunAsync(CancellationToken cancellationToken)
    {
        while (!cancellationToken.IsCancellationRequested)
        {
            Trace.TraceInformation("Working");

            // Do the actual work
            var tasks = new List<Task>
            {
                Task.Factory.StartNew(() => new Processor().ProcessMessageFiles(), cancellationToken),
                Task.Factory.StartNew(() => new Processor().ProcessFirmware(), cancellationToken)
            };

            Task.WaitAll(tasks.ToArray(), cancellationToken);

            // Delay the loop for a certain time
            await Task.Delay(WebEnvironment.Instance.DatabasePollInterval, cancellationToken);
        }
    }
}

最佳答案

我会做一些不同的事情:

  1. OnStart 应及时执行。常见的做法是将工作推迟到负责执行实际工作的后台线程。您实际上正在这样做,但是通过调用 Task.Wait 来阻塞该线程,这使得卸载到后台线程变得无用,因为执行再次变为同步。
  2. 您正在使用sync over async anti-pattern ,这应该尽量避免。让调用方法并行调用工作。
  3. 我认为您可能会以相反的方式使用ManualResetEvent。您将 RunAsync 方法包装在 try-finally block 中,但仅从 OnStop 调用 WaitOne >。我不太确定您是否需要锁,(从您当前的代码来看)似乎没有并行调用此代码。相反,您可以将 RunAsync 返回的 Task 存储在字段中并等待其完成。
  4. 您正在使用阻塞版本WaitAll。相反,您可以使用异步版本 Task.WhenAll,它可以异步等待。

关于c# - Windows 服务内的 TPL,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29528302/

相关文章:

c# - 如何验证 KeyUsage 的证书

c# - 避免应用程序内存不足异常的最佳方法

c# - Parallel.ForEach无法按预期的方式运行C#

c# - 不同 DbContext 的并行执行比非并行版本慢

java - 从java启动windows服务

c# - 在 Select LINQ 方法中使用 Task.Run()

c# - Powershell.exe - 无法编译使用 var 的 C# 代码

c# - 绑定(bind)到不带参数的成员函数?

powershell - 使用 PowerShell 获取 Windows Server 上所有已停止自动服务的属性

c# - 定期运行的 Windows 服务