【问题标题】:C# Why is interrupting a Task not supported? [duplicate]C# 为什么不支持中断任务? [复制]
【发布时间】:2016-10-07 23:05:57
【问题描述】:

线程支持中断。为什么没有任务?

从我(不知情的)角度来看,允许 Task 支持中断似乎是合理的:

  • 如果任务当前没有在线程上执行,调用 task.Interrupt() 将设置一个 TaskInterruptException,以便在计划任务时抛出。
  • 否则,TaskInterrupException 将在执行任务的线程中抛出,该异常将在任务中捕获或添加到顶部的 AggregateException。我猜这个功能需要任务知道正在执行的线程(这不合理吗?)

实现此功能所需的部分是否已经存在,或者这是否需要更改语言实现?

补充: 我已经阅读了许多关于 SO 的问题,这些问题讨论了杀死/中止任务,其相关答案讨论了 CancellationToken 和(不鼓励的)Thread.Abort 方法。

在我自己的摆弄中,我发现用 CancellationToken.Register 注册 Thread.Interrupt 并不会中断任务中运行的线程,而是会中断对令牌调用取消的线程。

因此,在我看来,仍然需要一个经过批准的功能,允许开发人员确保可以(温和地)终止任务。

我还将补充(以免有人说“重写您的任务以获取 CancellationTokens”)此功能在开发人员确实拥有任务中正在执行的代码的情况下特别有价值.

而且,从原则上讲,似乎应该有一种方法让任务的执行者能够提供取消的保证,而不是依赖任务的实施者通过取消来正确地做事令牌。

另一个补充: 不管风险如何,C# API 都支持Thread.AbortThread.Interrupt。所以我的问题是,本质上,为什么Task 不支持相同的 API(具有相同的固有风险)?

更新
该帖子已被标记为与this question 重复。但是,在发布这个问题(以及所有答案)之前,我已经阅读了引用的问题 - 这个问题不是重复的,而是一个寻求更多信息的相关问题。这个问题问“你能中止吗”,答案基本上是“你不应该中止”——我的问题是“鉴于中断比中止更好,为什么不中断受支持的功能?哪些机械障碍禁止此功能?”。根据this question 的说法,中断中止线程之间存在重要区别,并且更倾向于使用中断。

【问题讨论】:

  • 谢谢你的链接,汉斯。你在那里讨论 Thread.Abort。 Thread.Interrupt 也一样吗?我知道 Thread.Interrupt 应该避免在讨厌的位置抛出异常。
  • 另外,不管有什么风险,API 仍然支持 Thread.Abort 和 Thread.Interrupt。我的问题是为什么不支持相同的任务?
  • 如果您认为需要中止第三方代码,那么您确实必须在单独的应用程序域或进程中运行该代码。这是彻底中止的唯一方法。否则你应该使用合作取消模型。

标签: c# task interrupt


【解决方案1】:

而且,从原则上讲,似乎应该有一种方法让任务的执行者能够提供取消的保证,而不是依赖任务的实施者通过取消来正确地做事令牌。

我不同意这种说法。任何困难都有可能使您的系统处于未确定状态,无法继续正常运行,尤其是当您尝试中止不属于您的代码的任务时。

如此设计的优雅取消任务是避免这种情况的唯一方法。您是否更喜欢生产中的系统(设计为 24/7 运行)来泄漏资源并意外崩溃,或者在您无法取消不需要的 Task 时浪费一些额外的资源和时间在CacnellationToken?

这是我的个人意见,我发现Task.Abort() 在大多数情况下有害而不是有用。

编辑:此外,Task 只是一个操作句柄,您可以创建一个TaskCompletionSource<T> 并在任何线程上的任何时间点设置完成,所以这是不可能的跟踪Task 背后的逻辑代码实际运行的线程。例如,Task.WhenAll(Task[]) 返回一个Task。你将如何中止它?它不在任何线程上运行,而是在完成给定任务时进行侦听。 IE。添加通用的 Abort 方法在技术上是不可行的。

【讨论】:

  • Serge,我很高兴你添加了编辑 - 这就是我在这个问题中寻找的信息。重申:“支持任务的实际代码和任务句柄可能没有连接,因此无法通过任务识别需要中断的代码。”
  • 我了解用于 24/7 运行的代码永远不会想要中止线程。但是,我的用例是按小时付费运行的计算管道。如果出现问题,我们希望尽快关闭所有内容(这样用户就不会被收取额外费用),同时还要尽可能准确地分类错误来源(这样我们就可以解决管道中的问题)。
  • 使用一些包装器,Thread.Abort()Thread.ResetAbort(),强制中止Task 在技术上仍然是可行的。您可以在 SO 上添加另一个问题,具体说明如何做到这一点 - 因为这是在您的特定情况下解决问题的唯一最便宜的方法。
猜你喜欢
  • 2011-03-24
  • 2011-03-17
  • 2011-04-16
  • 1970-01-01
  • 2015-05-23
  • 2014-09-13
  • 2014-11-18
  • 1970-01-01
相关资源
最近更新 更多