任务取消抛出异常

Task Cancellation Throwing Exception

所以,根据 this post 的回答:

2) If the body of the task is also monitoring the cancellation token and throws an OperationCanceledException containing that token (which is what ThrowIfCancellationRequested does), then when the task sees that OCE, it checks whether the OCE's token matches the Task's token. If it does, that exception is viewed as an acknowledgement of cooperative cancellation and the Task transitions to the Canceled state (rather than the Faulted state).

由此我了解到,通过将令牌传递给任务的构造函数,然后调用同一令牌的 ThrowIfCancellationRequested() 方法,任务实际上会和平终止,而无需我显式捕获 OperationCanceledException。

然而结果是抛出了一个异常,所以我相信我可能误解了这个机制。

我的代码:

  public void AI()
    {
        IsBusy = true;
        var token = stopGameCancellationTokenSource.Token;
        var workTask = new Task(() => aiWork(token), token);
        workTask.Start();
        workTask.ContinueWith(task => { IsBusy = false; });

    }

    private void aiWork(CancellationToken token)
    {

        while ( true)
        {

             //Some computation being done here

            token.ThrowIfCancellationRequested(); //Exception is thrown here, I thought it wouldn't

            //More computation here, which I don't want to happen if cancellation has benn requested
        }
    }

这一行

token.ThrowIfCancellationRequested();

明确抛出异常。 link 告诉你的是,如果任务的令牌与刚刚抛出的 OperationCanceledException 中的令牌匹配,"the Task transitions to the Canceled state (rather than the Faulted state)."

所以最重要的是,如果您不希望在取消任务时抛出异常,只需省略该行即可!

除了@JurgenCamilleri 中关于 为什么 出现错误的解释之外,您可能打算做的是循环直到请求取消。您可以通过将代码更改为如下内容来做到这一点:

private void aiWork(CancellationToken token)
{
    while (!token.IsCancellationRequested)
    {
        //Some computation being done here

        if (token.IsCancellationRequested)
            break; // need to cancel

        //More computation here, which I don't want to happen if cancellation has been requested
    }
}    

如方法名称所示,如果请求取消,ThrowIfCancellationRequested 将抛出异常 (OperationCanceledException)。

如果你真的不想抛出异常,你可以检查 token.IsCancellationRequested 是否为真,在这种情况下,退出你的函数。 但是,我建议坚持使用 token.ThrowIfCancellationRequested(),除非你有充分的理由不这样做。