Pergunta

When I cancel a Task, the await result still returns true for the IsCanceled Property. Seems something is going wrong.

Please advise. This is the code:

CancellationTokenSource _cancelLationToken = new CancellationTokenSource();

private async void Button_Click(object sender, EventArgs e)
{
    _cancelLationToken = new CancellationTokenSource();
    _cancelLationToken.Token.Register(theCallBack);
    var myTaskToWaitFor = Task.Factory.StartNew(() => WorkHard(_cancelLationToken.Token), _cancelLationToken.Token);
    await myTaskToWaitFor;

    int i=0;

    if(myTaskToWaitFor.IsCanceled)
        i = i; //breakpoint for debugging
    else
        i = i; //breakpoint for debugging <== always ends here... :-(
}

private void WorkHard(CancellationToken token)
{
    for(int i = 0; i < 100000000; i++)
        if(token.IsCancellationRequested)
            break;
        else
            Math.Acos(Math.Pow(i, i / 10000000));
}

public void theCallBack()
{
    //todo: do something
}

private void CancelButton_Click(object sender, EventArgs e)
{
    _cancelLationToken.Cancel();
}

When I hit the CancelButton and therefore trigger the CancelButton_Click method, the CallBack method is triggered. But... when I check myTaskToWaitFor.IsCanceled is always returns false and I get this info: Id = 1, Status = RanToCompletion, Method = "{null}". Why is the status not Cancelled or something?

When I use http://msdn.microsoft.com/en-us/library/system.threading.cancellationtoken.throwifcancellationrequested.aspx

like this:

private void WorkHard(CancellationToken token)
{
    for(int i = 0; i < 100000000; i++)
        if(token.IsCancellationRequested)
            token.ThrowIfCancellationRequested();
        else
            Math.Acos(Math.Pow(i, i / 10000000));
}

I only get some errors in debug mode and the it seems the myTaskToWaitFor is actually cancelled, but the code doesn't continue (on continue the program is shut down due to the exception). Any thoughts? Kind regards,

Matthijs

Edit:

test with the TrowIfCancellationRequested was based on "When you call ThrowIfCancellationRequested on a CancellationToken which is canceled, it will throw an OperationCanceledException. The Task Parallel Library knows that this type of exception represents cancellation rather than a failure, and will treat it differently. For example, Task has a property called IsCanceled that automatically becomes true when an OperationCanceledException is thrown while executing an async method." From the book Async in C# 5.0 by Alex Davies.

That's why I thought I could expect myTaskToWaitFor.IsCancelled to return true and the code would continue.

Foi útil?

Solução

The ThrowIfCancellationRequested() is the ideal way of signalling that you are existing due to observing cancellation. This will present itself as an exception at the caller, but you can handle that by having a try / catch around the await, and simply checking the reasons there - either on the task, or by inspecting the AggregateException.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top