【问题标题】:How could I abort an awaited task?我怎么能中止等待的任务?
【发布时间】:2016-11-04 08:45:07
【问题描述】:

我最近很快了解到,在我的上下文中,所有 Cancellation 令牌的价值在于阻止任务被安排。我有长时间运行的单一方法任务,我需要在等待的任务中中止这些任务。我怎样才能做到这一点?

我的第一个想法是让另一个线程为长时间运行的方法运行,但在此之上有一个循环不断检查是否Cancellation.IsCancelled == true,当它是true 时,我中止托管长期运行方法的线程。

这很糟糕吗?还有其他方法吗?

顺便说一句,我的长时间运行的任务是一个单一的方法,所以我可以在它开始运行之前或在它运行之后检查取消令牌,让我没有机会在它完成之前停止长时间运行的方法,例如,收集所有FileInfo 驱动器 C 上每个文件的对象:!这是长时间运行的代码:

FileInfos = Mapper.Map<ObservableCollection<FileInfoViewModel>>(dirInfo.GetFiles($"*.{ext.TrimStart('.')}", SearchOption.AllDirectories));

我可以将其拆分为两个调用,并检查它们之间的令牌,但这不会产生太大影响,或者我可以将 CLR 代码重写为我自己的代码,并手动使用检查令牌的循环。这会起作用,但它闻起来很糟糕。

【问题讨论】:

  • Yes, it's bad。调用Thread.Abort() 应该被视为一个错误。您需要进行合作取消 - 被取消的线程需要定期检查它是否已被取消,并做出相应的反应。如果它不能做到这一点,那么放弃它可能更安全。
  • 你必须描述你的任务是做什么的以及为什么取消令牌不可用
  • @SamiKuhmonen 请看我的编辑。
  • 您可以通过隔离它并使主代码继续进行来伪造取消不间断代码,例如Task.WhenAny(actualWork, someCancellation).

标签: c# multithreading asynchronous async-await cancellation-token


【解决方案1】:

用于枚举文件系统实体的底层系统 API 已经支持取消 - 您只需确保使用正确的托管 API。

DirectoryInfo.GetFiles 会将可枚举转换为数组 - 这意味着它仅在收集完所有数据后才返回。另一方面,DirectoryInfo.EnumerateFiles 将直接暴露可枚举,您可以在任何时候轻松停止评估。

仍有一些不可中断的位,但Thread.Abort 无论如何也帮不了你 - Thread.Abort 只会在线程处于托管代码中时杀死它们,而所有真正需要时间的东西都是本机的,使用FindFirstFile/FindNextFile API。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-19
    • 2017-01-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-06
    相关资源
    最近更新 更多