【问题标题】:Cancelling a Task, using multiple CancellationSourceTokens取消一个任务,使用多个 CancellationSourceTokens
【发布时间】:2019-12-13 10:49:17
【问题描述】:

我有一个用于创建新令牌源的“开始”按钮和一个用于取消令牌源的“停止”按钮。

我在类中的函数之外定义了取消令牌源:

public static CancellationTokenSource cts;

当您单击开始按钮时,我将以下任务设置为在开始后 10 秒后运行:

cts = new CancellationTokenSource();
Task.Delay(10000).ContinueWith((x) => PostGoingReport(cts));

在方法内部,我正在检查以确保令牌在运行前没有被取消:

if (cts.IsCancellationRequested )
{
    return;
}

在停止按钮中我有:

cts.Cancel();

当您单击开始按钮,然后单击停止按钮时,它会按预期工作并且不会发布报告。

但是,如果单击开始按钮,然后停止,然后再次单击开始按钮,任务会运行两次。 这是因为我正在创建相同的 CancellationTokenSource 实例,因此不再请求取消令牌源。

有没有办法让任务链接到特定的令牌源?

我问这个的原因是因为我的应用程序“睡眠”并在特定时间之间取消所有任务然后醒来,它似乎醒来并发布报告两次而不是一次。

【问题讨论】:

  • 不要使用全局变量来保存 CTS。也不要让延迟丢失。这段代码的编写方式可能会在您关闭表单 10 秒后出现异常。如果您想跟踪多个任务和 CTS,请将它们放在一个容器中,例如列表或队列。您还必须决定该按钮取消的什么。最老的任务?最新任务?
  • 您没有告诉Task.DelayContinueWith 涉及CancellationToken,并且您的委托意味着将延迟执行PostGoingReport(cts),这意味着它将捕获cts 在执行时处于活动状态。如果您开始,然后停止,然后开始,您的代码将使用第二个令牌,而不是第一个。
  • 简而言之,不要使用全局令牌变量,在 Start 方法中捕获当前的 CancellationToken 并将其传递给 Task.DelayTask.ContinueWith 以及您的方法(不应该取一个CancellationTokenSource 但一个CancellationToken)
  • 我需要 cts 作为全局变量,因为我在其他区域使用它,例如停止按钮,如果它的本地我不能使用它或将它传递给停止按钮。跨度>
  • 刚刚注意到我一直在使用:await Function(cts) 然后检查函数内部的令牌而不是 Task.Run(Function(),ct.Token) 愚蠢的我。

标签: c# task token cancellation


【解决方案1】:

你需要稍微重写你的代码:

  1. 重组您的方法以采用 CancellationToken 而不是 CancellationTokenSource
  2. 将此令牌传递给Task.DelayTask.ContinueWith 以及您的PostGoingReport 方法(因此需要获取令牌,而不是源)
  3. start 方法应该构造一个新的源,获取它的令牌并按上述方式传递它

这就是您的 Start 方法的外观:

cts = new CancellationTokenSource();
var token = cts.Token;
Task.Delay(10000, token).ContinueWith((x) => PostGoingReport(token), token);

这可确保:

  1. 如果您在延迟过去之前取消,延迟将取消(并且 continuewith 任务不会执行)
  2. 如果您在延迟过后但在 lambda 执行之前立即取消,则 continuewith 任务不会调用它
  3. 您的 PostGoingReport 方法将使用构建它的源中的令牌,而不是实际执行时的任何当前令牌

【讨论】:

  • 谢谢。我现在将 Task.Run() 与其他函数以及令牌一起使用,而不是仅仅执行 await Func()。我的函数被包裹在一个 try catch 中,当我按下停止按钮时,我得到一个异常抛出到日志中。有没有办法让它忽略取消的任务,因为它们并不是真正的问题?
猜你喜欢
  • 2016-01-03
  • 2023-04-06
  • 1970-01-01
  • 2022-07-11
  • 1970-01-01
  • 1970-01-01
  • 2014-05-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多