如何强制取消任务?

12
假设有一个任务包括以下大致操作:
Task someTask = new Task(() => {

  while(!IsCancellationRequested) {

    Do_something_over_a_long_period_of_time();
    token.ThrowIfCancellationRequested();

    Do_something_over_a_long_period_of_time();
    token.ThrowIfCancellationRequested();

    Do_something_over_a_long_period_of_time();
    token.ThrowIfCancellationRequested();
  }
});
someTask.Start();

还有一些用户非常不耐烦,他们希望立即终止我的应用程序。他们不想在长时间运行的操作过程中等待。

我以前使用Thread类,并能够通过调用Abort()命令立即终止所有线程。

如何立即终止我的任务?

谢谢。


1
你看过BackgroundWorker了吗? - HadleyHope
1
@HadleyHope 如何使用后台工作器解决他的问题。它支持类似任务的取消功能。 - Kugel
2个回答

20

你不能以不合作的方式强制终止任务。以不受控制的方式中止线程是不安全的,因此是有意不支持的。

相反地,你应该使你的 Do_something_over_a_long_period_of_time 调用可以取消 (即通过向它们传递标记,并让它们也定期检查)。

编辑:正如另一个答案中所指出的那样,你可以通过确保所有前台线程已终止来杀死应用程序。但你需要知道你的任务不一定有机会 干净地 终止。如果它们正在执行诸如写文件之类的操作,则可能希望等待取消被注意到,以避免破坏持久化状态。


12
归根结底,“长时间执行某个操作”可能是一个第三方库调用,您无法修改以使其可协作取消。因此,强制取消这种类型的任务仍然是合理的现实需求。是的,在这种情况下杀死线程可能是安全的,也可能不安全,这取决于函数正在执行何种工作(如I/O等),但无论如何,必须有一种最佳方法来解决这个问题,而不是“不要这么做”。 - Jack Ukleja
@Schneider:嗯,这取决于你所说的“最好”的含义 - 如果你认为“只需终止线程,不关心我们是否丢失客户数据”比“不实现我们无法安全实现的功能”更好,那么是的,你可以这样做。开玩笑的语言放在一边,有时候这确实是前进的方式。但是,如果你说“必须有一种安全终止任意代码的方法”,那么我怀疑这只是一种愿望,而不是一个断言。 - Jon Skeet
1
我同意任意代码无法安全终止。我有一个具体的场景:我们正在运行一个CPU密集型的数学“求解器”,可能需要几分钟才能运行。它只是简单地计算数字,最终返回结果,但不进行I/O(尽管它可能分配未受管理的内存等)。我们必须能够取消这个过程,但我们不能改变库。我们该怎么办?我能想到的最好的解决方案是每个计算分离一个进程,或者使用一个AppDomain? - Jack Ukleja
@Schneider:单独的进程肯定更干净;AppDomain 可能也可以;老实说,我对于AppDomain分离的细节了解得不够充分,无法百分之百确定。 - Jon Skeet
突然间,我第一次看到*nix的fork有用处 :) - Jack Ukleja
显示剩余5条评论

3

他们希望立即终止我的应用程序。他们不想等待长时间运行的操作。

默认情况下,任务在线程池上作为后台任务运行。您可以安全地退出应用程序,而不必担心后台线程。

因此,只要您想退出进程,就没有问题。

请注意,Thread.Abort()虽然快速但不安全。即使是对于退出应用程序,它也很少会引起真正的问题。


8
我不认为我会说“没有问题” - 如果其中一个后台线程正在写入应用程序下次启动时需要的文件,那该怎么办? - Jon Skeet
我忘记了线程池和后台任务,现在它可以正常工作了。谢谢。 - Jean Louis

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接