我需要在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);
}
}
}
答案 0 :(得分:2)
我会做一些不同的事情:
OnStart
应该及时执行。通常的做法是将工作推迟到负责实际工作的后台线程。你实际上正在做那个,但通过调用Task.Wait
来阻止该线程,这种方式使得卸载到后台线程无用,因为执行再次变得同步。ManualResetEvent
反过来。您将RunAsync
方法包含在try-finally
块中,但只是从WaitOne
调用OnStop
。我根本不确定你是否需要一个锁,它(似乎是你当前的代码)似乎没有并行调用这个代码。相反,您可以将Task
返回的RunAsync
存储在一个字段中,然后等待它完成。WaitAll
。相反,您可以使用异步版本Task.WhenAll
,它可以异步等待。