In the past I have used timer to do polling job that retrieves the data from one database and insert into another after processing the data. I'm trying to write this with TPL (Task Parallel Library).
Is the following code with Task.Delay
, the efficient way to run a polling job in a window service with TPL?
When I said 'efficient' it means it doesn't consume more resources from the OS neither wasting. Jeffrey Ritcher in this Wintellect video on Thread Fundamentals strongly discourages to use Thread.Sleep
. His argument is that an app should not hold a thread if it is not using so other apps or the same app can use it from the thread pool.
I assume Task.Delay
internally doing a Thread Sleep
so I assume it is inefficient.
Another requirement is that this job also has to run every minute and overlapping should be avoided.
class Program
{
private CancellationTokenSource _cancellationTokenSource;
private Task _etlTask;
protected override void OnStart(string[] args)
{
_cancellationTokenSource = new CancellationTokenSource();
_etlTask = Task.Run(
async () =>
{
CancellationToken token = tokenSource.Token;
while (!token.IsCancellationRequested)
{
await etlJob.Run(); // An ETL Job to read from DB to update another DB
await Task.Delay(TimeSpan.FromMinutes(1), token);
}
});
}
protected override void OnStop()
{
_cancellationTokenSource.Cancel();
try
{
_etlTask.Wait();
}
catch (Exception e)
{
// handle exeption
}
}
}
Yes, your code looks fine.
This job has to run every minute and overlapping should be avoided.
The way it's currently structured, it has a minute of delay between executions, which is not quite the same thing as "running every minute". If that's good enough for you, I'd just keep it as-is.