【发布时间】:2013-09-15 06:57:29
【问题描述】:
当我取消任务时,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}”。 为什么状态不是Canceled之类的?
像这样:
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 实际上已取消,但代码没有继续(在继续时,程序由于异常而关闭)。 有什么想法吗? 亲切的问候,
马蒂斯
编辑:
使用 TrowIfCancellationRequested 的测试基于 "当您对已取消的 CancellationToken 调用 ThrowIfCancellationRequested 时, 它会抛出一个 OperationCanceledException。任务并行库知道 这种类型的异常代表取消而不是失败,并将处理 它不同。例如,Task 有一个名为 IsCanceled 的属性,它会自动 当执行异步时抛出 OperationCanceledException 时变为真 方法。”来自 Alex Davies 的 Async in C# 5.0 一书。
这就是为什么我认为我可以期望 myTaskToWaitFor.IsCancelled 返回 true 并且代码将继续。
【问题讨论】:
-
带有
ThrowIfCancellationRequested的版本是正确的 - 是否有异常行为?不过,预计这会报告一个异常 - 你需要处理它 -
在检查 myTaskToWaitForGetCashReport.IsCanceled 之前如何处理异常?如果我在“var myTaskToWaitFor = Task.Factory.StartNew(() => WorkHard(_cancelLationToken.Token), _cancelLationToken.Token); await myTaskToWaitFor;”周围添加一个 try catch myTaskToWaitFor 字段是未知的(当然......)。当我还在尝试中添加检查 myTaskToWaitFor.IsCanceled 时...我只去捕获部分。我是否需要在 try 之前创建一个 bool 字段并将其设置在 try 或 catch 中?那是唯一的解决方案吗? (myTaskToWaitFor.IsCanceled(当然)在捕获中是未知的)
-
你
try/catch在await周围。到那时该变量是已知的。 -
啊...听起来是个好主意 ;-) 这就是解决方案。谢谢
-
在
async代码as I describe on my blog 中,您应该更喜欢Task.Run而不是StartNew。
标签: c# task async-await cancellationtokensource