取消任务,使用多个CancellationSourceTokens

问题描述 投票:0回答:1

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

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

public static CancellationTokenSource cts;

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

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

在我正在检查以确保令牌在运行之前未被取消的方法内:

if (cts.IsCancellationRequested )
{
    return;
}

并且在停止按钮中,我有:

cts.Cancel();

[当您单击开始按钮,然后单击停止按钮时,它可以按预期运行,并且不会发布报告。

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

有没有一种方法可以使任务链接到该特定令牌源?

之所以这样问,是因为我的应用“休眠”并取消了某些小时之间的所有任务,然后唤醒,而且似乎唤醒并两次发布报告,而不是一次。

c# task token cancellation
1个回答
2
投票

您需要重新编写代码:

  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. 如果您在延迟过去之前取消,延迟将被取消(并且继续执行任务将不执行)
  2. 如果您在延迟过去之后但在执行lambda之前立即取消,则continuewith任务将不会调用它
  3. 您的PostGoingReport方法将使用其构造源中的令牌,而实际上不会执行时使用最新的令牌
© www.soinside.com 2019 - 2024. All rights reserved.