如何在使用ContinueWith时捕获OperationCanceledException
本文关键字:OperationCanceledException ContinueWith | 更新日期: 2023-09-27 17:49:13
我有一些代码,我正在从。net 4.5的可爱的async
和await
关键字降级到。net 4.0。我使用ContinueWith
来创建一个类似于await
工作方式的延续。
var tokenSource = newCancellationTokenSource();
var myTask = Task.Run(() =>
{
return MyStaticClass.DoStuff(tokenSource.Token);
}, tokenSource.Token);
try
{
var result = await myTask;
DoStuffWith(result);
}
catch (OperationCanceledException)
{
// Cancel gracefully.
}
(如人们所料,MyStaticClass.DoStuff(token)
经常调用token.ThrowIfCancellationRequested()
)
我的新代码看起来像这样:
var tokenSource = new CancellationTokenSource();
try
{
Task.Factory.StartNew(() =>
{
return MyStaticClass.DoStuff(tokenSource.Token);
}, tokenSource.Token)
.ContinueWith(task =>
{
var param = new object[1];
param[0] = task.Result;
// I need to use Invoke here because "DoStuffWith()" does UI stuff.
Invoke(new MyDelegate(DoStuffWith, param));
});
}
catch (OperationCanceledException)
{
// Cancel gracefully.
}
然而,OperationCanceledException
从未被捕获。这是怎么呢我把我的try/catch块放在哪里?
取消的处理方式与其他异常不同。基本上,您可以使用以下模式:
Task.Factory.StartNew(() =>
{
// The task
}, tokenSource.Token)
.ContinueWith(task =>
{
// The normal stuff
}, TaskContinuationOptions.OnlyOnRanToCompletion)
.ContinueWith(task =>
{
// Handle cancellation
}, TaskContinuationOptions.OnlyOnCanceled)
.ContinueWith(task =>
{
// Handle other exceptions
}, TaskContinuationOptions.OnlyOnFaulted);
或者另一个:
Task.Factory.StartNew(() =>
{
// The task
}, tokenSource.Token)
.ContinueWith(task =>
{
switch (task.Status)
{
case TaskStatus.RanToCompletion:
// The normal stuff
break;
case TaskStatus.Canceled:
// Handle cancellation
break;
case TaskStatus.Faulted:
// Handle other exceptions
break;
}
});
在你的例子中,你没有捕捉到任何东西,因为:
-
Task.Factory.StartNew
立即返回并且总是成功。 - 您的继续程序总是运行
- 访问
task.Result
抛出AggregateException
,因为任务被取消 异常不被任何东西处理,因为它是从线程池线程抛出的。哦。接下来会发生什么取决于框架版本:
- In .NET <4.5,一旦失败的任务完成,进程将被终止,因为你有一个未被观察到的异常。
- 在。net>= 4.5中,异常将被静默删除。