停止正在运行的线程的安全方法是啥?
Posted
技术标签:
【中文标题】停止正在运行的线程的安全方法是啥?【英文标题】:What is a safe way to stop a running thread?停止正在运行的线程的安全方法是什么? 【发布时间】:2012-02-14 05:50:44 【问题描述】:我有一个包含 IronPython 脚本执行的线程。出于某种原因,我可能需要随时停止这个线程,包括脚本执行。如何做到这一点?第一个想法是Thread.Abort()
,但众所周知是邪恶的……
【问题讨论】:
是的,从线下猛拉地毯是邪恶的。但是,如果这就是您想要做的,那么Thread.Abort()
就是您要走的路。更好的解决方案是修改应用程序的设计。
你的线程是循环还是只为执行单个脚本而运行然后死掉?
它循环,但每次迭代都包含脚本执行,可能相当长。
@CodyGray,你说的修改设计到底是什么意思?
这样您就不必“随时停止 [the] 线程”。问题中确实没有足够的背景信息让我给出更具体的建议。我的观点是,您对Thread.Abort
不理想是正确的,但这并不是那个邪恶的功能,而是它正在做的事情。而且因为它正在做你想做的事......
【参考方案1】:
什么是停止正在运行的线程的安全方法?
把线程放在它自己的进程中。当您希望它停止时,终止进程。
这是杀死线程的唯一安全方法。中止线程会严重破坏进程的稳定性并丢失用户数据。如果您真的,真的需要能够杀死一个可以做任何事情的线程,那么没有办法避免“丢失用户数据”的情况。避免破坏要求中止的进程的唯一方法是使它们完全不同的进程。
【讨论】:
就我而言,线程代码无法破坏整个过程的稳定性。但是对于常识 - 通过创建不同的流程,您意味着将两个项目编译为不同的程序集,其中一个运行另一个?还是什么? @chersanya:你似乎对自己非常有信心。你正在运行一个脚本;你怎么知道脚本的作者没有在其中放置会破坏进程稳定性或在中断时丢失用户数据的代码? @chersanya 不同的进程不一定需要运行不同的程序集。例如,myprogram.exe
可以启动一个运行 myprogram.exe
的新进程。
@Eric,这可能是真的,但也有缺点。一般来说,您不想只是绕过杀死进程。相反,您想向他们发送信号或消息,告诉他们停止。如果进程正在管理一些资源,这非常重要,因此它可以将资源恢复到一致的状态。对于某些资源(如文件锁或信号量),操作系统可以重新设置它们(可能会以不一致的状态暴露一些其他资源),但并非全部,副作用通常是不希望的。
@KevinCathcart:嗯,当然。但如果你有能力礼貌地控制进程,那么你肯定也有能力礼貌地控制线程。如果你可以建立一个控制系统,那么一定要这样做;我理解这个问题是“但是如果我无法控制代码但我希望它现在停止,我该怎么办?”【参考方案2】:
根据您的问题和后续的 cmets,我可以建议您两个选项,以及一些额外的“警告”:
如果您的线程在每次迭代时循环执行某些操作,您可以设置一个 volatile 布尔标志,使其在完成当前迭代后退出(伪代码,因为我不熟悉 python):
while shouldExit = false
// do stuff
然后,当您希望线程停止时,只需将标志设置为true
,它将在下次检查条件时停止。
【讨论】:
第一个解决方案很明显,但不适用于我的情况。我害怕使用Thread.Abort()
,因为到处都有人写“永远不要使用它!!!”)))。但现在我在程序中使用它 - ho 句柄可能保持打开状态。
确实大多数时候它很糟糕,但特别是因为人们倾向于将线程用于 I/O 或其他类似的事情,如果线程被杀死,这些事情将处于不一致的状态。如果您没有将线程用于这样的事情,那么它是非常安全的。
是否可以保证,在调用Abort()
后,具有try // do work - no try/catches here catch(ThreadAbortException) // log exit
之类代码的线程将被停止?
@chersanya:绝对不是。这是没有办法保证的。特别是,如果您在尝试中止的线程中运行恶意代码,那么您已经输了;恶意代码可以忽略线程中止。中止一个线程应该被认为是对它离开的线程的措辞强硬的建议;如果写得巧妙,对那个意图怀有敌意的线程可以随意忽略它。
@Tudor:进一步扩展您的观点:您知道什么比打开文件句柄更糟糕吗? 当只有一半的用户数据被缓冲出来时关闭文件句柄,使文档处于损坏状态,以至于用户的数据都无法恢复。与锁类似;让显示器处于进入状态是不好的。在完成对关键用户数据的受保护编辑的代码之前退出监视器更糟糕。人们表现得好像中止线程是不好的,因为它留下句柄分配,但实际的问题是它经常过早释放它们。以上是关于停止正在运行的线程的安全方法是啥?的主要内容,如果未能解决你的问题,请参考以下文章