【问题标题】:Is there any elegant way to cancel/stop a long running thread?有什么优雅的方法可以取消/停止长时间运行的线程吗?
【发布时间】:2012-10-29 04:27:54
【问题描述】:

我知道 TPL 中的 CancellationToken 支持,但是(IMO)只有在我有适当的 token.ThrowifCancellationRequested() 时才能工作,这在我的场景中是不可能的。

有没有其他优雅的方式(除了完全中止线程)来实现这一点?

我不关心线程的事务状态。 我不在乎线程停止/取消的状态。

感谢您的关注!

更多详情: 我需要生成一个新线程(任务/线程池/线程)来调用一个 API,该 API 调用多个存储过程来获取近 100 万条记录,然后它对每条记录进行一些修饰(业务计算)。 最后,此 API 返回一个数据表,该数据表是一份业务重要报告。 如果需要,我想为用户提供中途取消此处理的选项。例如,如果设置了错误的过滤器集。 API only 执行只读操作,因此不需要事务管理。

【问题讨论】:

  • 如果你没有令牌,你有什么做什么?只是线程的句柄?
  • 这种情况是从线程调用外部库,而外部库没有取消方法吗?
  • 稍微改写:请提供有关您的方案的更多详细信息。这个问题太模糊了,恕我直言,无法给出有意义的答案。
  • @Ic。我在上面添加了更多细节。我可以灵活地拥有线程的令牌/句柄。只需要一种优雅的方式在单独的线程中调用耗时处理,并可以选择取消它。
  • 在这种情况下,这很棘手,因为没有好方法来清理终止作业留下的混乱 - 它可能不需要事务保证,但您可能会关心是否所有数据库连接都被泄露发生中止时。

标签: c# multithreading task-parallel-library


【解决方案1】:

要正确执行此操作,您应该通过取消令牌使用 Task 类中的内置方法,或者使用取消后台工作程序。或者,您可以尝试使用volatile bool 来检查用户请求是否已被取消。但是,volatile bools 在不同的架构(单/多处理器)中表现不一致。或者,您可以使用*ResetEvents 来指示调用了取消。这一切都需要在 API 本身中完成,否则它如何知道何时检查取消条件?您将无法优雅地取消它。

当然,永远不要在线程上调用Abort - 这是邪恶的,可能会使整个应用程序处于未定义状态,除非您打算重新启动整个应用程序,否则不要调用它。

奖励建议

还可以考虑在数据库端进行所有处理工作。不要将非常少量的记录带到客户端,比如说 1k 是一个很好的实用阈值。考虑这样一种情况,即许多用户请求不同的报告,这些报告都加载了一个服务器那么 - 这不能很好地扩展。此外,服务器在数据处理方面非常高效,并且它们身边有数据 - 已完成大量优化(CPU 线路缓存、快速内存访问等)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-11-10
    • 1970-01-01
    • 2021-03-04
    • 1970-01-01
    • 2012-04-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多