使用ContinueWith自我继续任务

时间:2015-01-27 12:39:15

标签: c# .net task-parallel-library async-await

我有一项需要定期运行的任务。我的第一个实现就像:

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");
}

此任务是这样开始的:

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

然后我想而不是在任务中循环,为什么不使用ContinueWith重新安排它呢?我的下一个实现是这样的:

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);
}

第二个实现更容易读写,我的测试显示没有区别,但我仍然想知道一个任务是否有缺点继续自己?

1 个答案:

答案 0 :(得分:5)

  

我仍然想知道ContinueWith的任务是否存在缺陷   本身?

坦率地说,我发现你的代码在连续附加时可读性较差(但这只是基于味道的)。我看到的唯一缺点就是您在令牌上使用了WaitHandle,这迫使您现在dispose your CancellationToken object

  

访问此属性会导致WaitHandle被实例化。它是   最好只在必要时才使用这个属性,然后再使用   处理相关的CancellationTokenSource实例   最早的机会(处理来源将处理此事   分配句柄)。手柄不应关闭或处理   直接

相反,我发现模式Task.Delay更清晰可读:

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");
}

然后当您想要停止Task时,请通过CancellationTokenSource取消。