1

I have a task that needs to run periodically. My first implementation was like:

public static void CheckTask(CancellationTokenSource tokenSource)
{
   do
   {
      // Do some processing
      Console.WriteLine("Processing");

      // Sleep awhile and wait for cancellation
      // If not cancelled, repeat
   } while (!tokenSource.Token.WaitHandle.WaitOne(1500));

   Console.WriteLine("Bye bye");
}

This task is started like so:

CancellationTokenSource tokenSource = new CancellationTokenSource();
Task task = null;
task = new Task((x)=> {
    CheckTask(tokenSource);
    //CheckTask2(t, (object)tokenSource);
}, tokenSource.Token);
task.Start();

Then I thought instead of looping in the task, why not reschedule it using ContinueWith? My next implementation was like this:

public static void CheckTask2(Task task, object objParam)
{
   CancellationTokenSource tokenSource = (CancellationTokenSource)objParam;
   // Do some processing
   Console.WriteLine("Processing");
   // Sleep awhile and wait for cancellation
   if(tokenSource.Token.WaitHandle.WaitOne(1500))
   {
      Console.WriteLine("Cancel requested");
      return;
   }
   // Reschedule
   task.ContinueWith(CheckTask2, tokenSource);
}

The second implementation is much easier to read and write and my tests showed no difference but I still wonder if there are drawbacks for a task to ContinueWith itself?

Yuval Itzchakov
  • 146,575
  • 32
  • 257
  • 321
mll5
  • 193
  • 2
  • 10
  • I think this question is more suited for http://programmers.stackexchange.com. That being said, it seems like the accepted pattern (see [this question on msdn](https://social.msdn.microsoft.com/Forums/en-US/d3f4f460-7d35-4406-b427-9c77bbbe6b55/repeating-tasks?forum=tpldataflow) ); see also [this question and answers](http://stackoverflow.com/questions/18999827/a-pattern-for-self-cancelling-and-restarting-task) for a cancellation pattern using await and async, which could or could not be relevant :p – Kilazur Jan 27 '15 at 12:43
  • There are associated startup costs with creating a Task (which `ContinueWith` is doing), but those should be negligible. If it works for you and makes the code cleaner: go ahead. – Jcl Jan 27 '15 at 12:43

1 Answers1

5

I still wonder if there are drawbacks for a task to ContinueWith itself?

Frankly, i find your code less readable with the continuation attached (but that is only flavor based). The only drawback i see is the fact that you use a WaitHandle on the token which forces you now to dispose your CancellationToken object:

Accessing this property causes a WaitHandle to be instantiated. It is preferable to only use this property when necessary, and to then dispose the associated CancellationTokenSource instance at the earliest opportunity (disposing the source will dispose of this allocated handle). The handle should not be closed or disposed directly.

Instead, I find the pattern with a Task.Delay more clean and readable:

public static async Task CheckTask(CancellationToken token)
{
   do
   {
      // Do some processing
      Console.WriteLine("Processing");

      await Task.Delay(1500, token);
   } while (!token.IsCancellationRequested);

   Console.WriteLine("Bye bye");
}

And then when you want to stop your Task, cancel its via CancellationTokenSource.

Yuval Itzchakov
  • 146,575
  • 32
  • 257
  • 321