任务IsCanceled是假的,而我取消了

时间:2013-09-11 09:53:59

标签: c# task async-await cancellationtokensource

当我取消任务时,等待结果仍然为IsCanceled属性返回true。似乎出现了问题。

请指教。 这是代码:

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();
}

当我点击CancelButton并因此触发CancelButton_Click方法时,会触发CallBack方法。但是......当我检查myTaskToWaitFor.IsCanceled总是返回false并且我得到这个信息:Id = 1,Status = RanToCompletion,Method =“{null}”。 为什么状态未被取消?或者什么?

当我使用http://msdn.microsoft.com/en-us/library/system.threading.cancellationtoken.throwifcancellationrequested.aspx

时 像这样:

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

我只在调试模式下出现一些错误,似乎myTaskToWaitFor实际上被取消了,但代码没有继续(继续程序由于异常而关闭)。 有什么想法吗? 亲切的问候,

Matthijs

修改

使用TrowIfCancellationRequested进行测试是基于的 “当您在取消的CancellationToken上调用ThrowIfCancellationRequested时, 它将抛出OperationCanceledException。任务并行库知道 这种类型的异常代表取消而不是失败,并将予以对待 它不同。例如,Task有一个名为IsCanceled的属性,它自动生成 在执行异步时抛出OperationCanceledException时变为true 方法。“来自Alex Davies的C#5.0中的Async一书。

这就是为什么我认为我可以期待myTaskToWaitFor.IsCancelled返回true并且代码会继续。

1 个答案:

答案 0 :(得分:7)

由于观察取消,ThrowIfCancellationRequested()是发信号通知你的理想方式。此作为调用者的例外情况出现,但您可以通过try周围catch / await处理此问题,并简单地检查原因在那里 - 要么在任务上,要么通过检查AggregateException