【发布时间】:2019-12-01 23:04:40
【问题描述】:
背景:
我有一个启动长时间运行(和无状态)任务的 Web 应用程序:
var task = Task.Run(() => await DoWork(foo))
task.Wait();
因为它们运行时间很长,我需要能够从单独的网络请求中取消它们。
为此,我想使用 CancellationToken 并在取消令牌后立即抛出异常。但是,根据我的阅读,任务取消是cooperative,这意味着任务正在运行的代码必须明确检查令牌以查看是否已发出取消请求(例如CancellationToken.ThrowIfCancellation())
我想避免到处检查CancellationToken.ThrowIfCancellation(),因为这个任务很长并且要经过很多功能。我想我可以完成我想要创建一个明确的Thread,但我真的很想避免手动线程管理。那就是……
问题:
是否可以在任务被取消时自动抛出异常,如果没有,是否有任何好的替代方案(模式等)来减少CancellationToken.ThrowIfCancellation()对代码的污染?
我想避免这样的事情:
async Task<Bar> DoWork(Foo foo)
{
CancellationToken.ThrowIfCancellation()
await DoStuff1();
CancellationToken.ThrowIfCancellation()
await DoStuff2();
CancellationToken.ThrowIfCancellation()
await DoStuff3();
...
}
我觉得这个问题与this one 有很大的不同,因为我明确要求一种方法来最小化检查取消令牌的调用,接受的答案会响应“不时地,在函数内部,调用token.ThrowIfCancellationRequested()"
【问题讨论】:
-
"是否可以在任务被取消时自动抛出异常" 否。 CancellationToken 用于询问“请停止”,而不是用于强制终止任务。任务必须“听取”这些停止请求。
-
谢谢@Greg - 那么,有什么我可以使用(CancellationToken 或其他)来取消任务,还是我或多或少地坚持这种方法?
-
我不确定是否有任何替代方案,但我建议您遵循微软的模式。这将使与使用 Tasks 和 CancellationTokens 的其他库(如 ASP.NET 和 System.Data.SqlClient)的集成变得更加容易。
-
1) 通过子线程长时间运行的计算任务在 Web 应用程序中通常是个坏主意(AppPool 可以回收)2) 旋转将
Task提高到Wait()有点违背了目的3) 是的,您“卡住” 可悲的是 -
@MickyD 1) 这是一个很好的观点 - 我实际上正在将一个 exe 转换为一个 Web 应用程序,所以我必须再分析一下。 2)没错,虽然我只是用它作为一个简单的例子。 3)¯\_(ツ)_/¯
标签: c# task cancellation