【问题标题】:Self continuing Task using ContinueWith使用 ContinueWith 的自我继续任务
【发布时间】:2023-03-23 14:45:01
【问题描述】:

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

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

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

【问题讨论】:

  • 我觉得这个问题更适合programmers.stackexchange.com。话虽如此,这似乎是公认的模式(见this question on msdn);另请参阅this question and answers 以了解使用 await 和 async 的取消模式,这可能相关也可能不相关:p
  • 创建一个任务(ContinueWith 正在做的)有相关的启动成本,但这些应该可以忽略不计。如果它适合您并使代码更清晰:请继续。

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


【解决方案1】:

我仍然想知道 ContinueWith 的任务是否有缺点 自己?

坦率地说,我发现您的代码在附加的延续中不太可读(但这只是基于风味的)。我看到的唯一缺点是您在令牌上使用了WaitHandle,这迫使您现在必须使用dispose your CancellationToken object

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

相反,我发现带有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取消它。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-02
    • 1970-01-01
    • 1970-01-01
    • 2015-04-10
    相关资源
    最近更新 更多