获取任务取消语句

Sib*_*Guy 22 .net c# multithreading cancellation-token

我可以在执行任务操作期间获取CancellationToken传递给Task构造函数的内容.大多数样本看起来像这样:

CancellationTokenSource cts = new CancellationTokenSource();
CancellationToken token = cts.Token;

Task myTask = Task.Factory.StartNew(() =>
{
    for (...)
    {
        token.ThrowIfCancellationRequested();

        // Body of for loop.
    }
}, token);
Run Code Online (Sandbox Code Playgroud)

但是如果我的行为不是lambda而是放在其他类中的方法并且我没有直接访问权限token呢?唯一的方法是通过token国家?

Ser*_*rvy 12

我可以获得在任务操作执行期间传递给Task构造函数的CancellationToken吗?

不,你不能直接从Task对象得到它,不.

但是如果我的动作不是lambda而是放在其他类中的方法而且我没有直接访问令牌呢?唯一的方法是将令牌作为状态传递吗?

这是两个选项,是的.还有其他人.(可能不是包容性列表.)

  1. 您可以使用匿名方法关闭取消令牌

  2. 你可以把它作为状态传递给你

  3. 您可以确保用于任务委托的实例具有一个保留在取消令牌上的实例字段,或者保留一些保留在令牌上的对象等.

  4. 您可以将令牌通过其他更大的范围公开为状态,即作为公共静态字段(在大多数情况下是不好的做法,但有时可能适用)


Ree*_*sey 10

但是如果我的动作不是lambda而是放在其他类中的方法而且我没有直接访问令牌呢?唯一的方法是将令牌作为状态传递吗?

是的,在这种情况下,您需要将标记框作为状态传递,或者包含在您用作状态的其他类型中.

但是,只有在计划使用CancellationToken方法时才需要这样做.例如,如果您需要打电话token.ThrowIfCancellationRequested().

如果您只是使用令牌来阻止安排该方法,那么它不是必需的.

  • 如果您想将它传递给在任务中启动的子任务,您还需要这是一个常见的事情.我希望`Task`暴露出它给出的CancellationToken. (7认同)

Bit*_*777 8

正如其他答案所述,您可以将令牌作为参数传递给您的方法.但是,重要的是要记住,您仍然希望将其传递给它Task.Task.Factory.StartNew( () => YourMethod(token), token), 例如.

这可以确保:

  1. Task如果在Task执行之前发生取消,则不会运行(这是一个很好的优化)

  2. 一个OperationCanceledException被调用的方法抛出正确转换任务的Canceled状态


Fun*_*lad 8

这似乎有效:

public static CancellationToken GetCancellationToken(this Task task)
{
  return new TaskCanceledException(task).CancellationToken;
}
Run Code Online (Sandbox Code Playgroud)

这对于使通用任务助手保留已取消任务的 CancellationToken 是必要的(我在尝试使Jon Skeet 的 WithAllExceptions 方法保留令牌时到达这里)。