简体   繁体   中英

Task Cancellation Throwing Exception

So, according to an answer to 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).

From this I understood that by passing a token to the constructor of the task and then calling that same token's ThrowIfCancellationRequested() method, the task would in fact terminate peacefully, without me having to catch the OperationCanceledException explicitly.

However as it turns out, an exception is thrown, so I believe I may have misunderstood the mechanic.

My code:

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

This line

token.ThrowIfCancellationRequested();

explicitly throws an exception. What the link was telling you is that if the token of the task matches the token in the OperationCanceledException that has just been thrown, "the Task transitions to the Canceled state (rather than the Faulted state)."

So the bottom line is if you don't want an exception to be thrown when the task is canceled, simply omit that line!

In addition to the explanation in @JurgenCamilleri answer of why you are getting the error, what you likely intended to do was loop until cancellation was requested. You can do that by changing your code to something like this:

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

As the name of the method suggests, ThrowIfCancellationRequested will throw an exception ( OperationCanceledException ) if a cancelletion was requested.

If you really don't want an exception to be thrown, you can check if token.IsCancellationRequested is true and, in this case, exit your function. However, I'd recommand sticking with token.ThrowIfCancellationRequested() unless you got good reasons not to.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM