C# 使用ContinueWith的自延续任务

C# 使用ContinueWith的自延续任务,c#,.net,task-parallel-library,async-await,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, repea

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

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);
}
第二个实现更易于阅读和编写,我的测试也没有显示出任何差异,但我仍然想知道任务本身是否存在缺陷

我仍然想知道是否有缺点的任务继续下去 本身

坦率地说,我发现您的代码在附加了continuation之后可读性较差(但这只是基于味道)。我看到的唯一缺点是,您在令牌上使用了
WaitHandle
,这迫使您现在:

访问此属性会导致实例化WaitHandle。它是 最好仅在必要时使用此属性,然后 在以下位置处置关联的CancellationTokenSource实例: 最早的机会(处置源将处置此 已分配句柄)。手柄不应关闭或弃置 直接的

相反,我发现模式中有一个
任务。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");
}
然后,当您想停止
任务时,请通过
CancellationTokenSource
取消其任务

我仍然想知道是否有缺点的任务继续下去 本身

坦率地说,我发现您的代码在附加了continuation之后可读性较差(但这只是基于味道)。我看到的唯一缺点是,您在令牌上使用了
WaitHandle
,这迫使您现在:

访问此属性会导致实例化WaitHandle。它是 最好仅在必要时使用此属性,然后 在以下位置处置关联的CancellationTokenSource实例: 最早的机会(处置源将处置此 已分配句柄)。手柄不应关闭或弃置 直接的

相反,我发现模式中有一个
任务。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");
}

然后当你想停止你的
任务时,通过
CancellationTokenSource

取消它,我认为这个问题更适合你。也就是说,这似乎是公认的模式(参见);另请参阅使用wait和async的取消模式,这可能相关,也可能不相关:p创建任务时会产生相关的启动成本(这是
ContinueWith
正在做的),但这些成本应该可以忽略不计。如果它对你有效并且使代码更简洁:继续。我认为这个问题更适合你。也就是说,这似乎是公认的模式(参见);另请参阅使用wait和async的取消模式,这可能相关,也可能不相关:p创建任务时会产生相关的启动成本(这是
ContinueWith
正在做的),但这些成本应该可以忽略不计。如果它对您有效并使代码更干净:继续。