使用Thread.Abort()有什么问题

Jan*_*ter 62 .net c# multithreading

所以我知道你不应该使用

Thread.Abort()
Run Code Online (Sandbox Code Playgroud)

但我从未得到过很好的解释.是否存在性能损失或隐藏的问题?

我知道你不能忽略/吞下ThreadAbortException(这是有道理的)

Eri*_*ert 80

除了这里所有其他好的答案之外,让我补充说,无法保证调用Thread.Abort实际上会中止有问题的线程.有可能(虽然不是特别容易)"强化"线程以防止被中止.例如,如果您因为认为它运行恶意代码而中止线程,则恶意代码可能会抵制其自身的破坏.

如果你有一个长期运行的操作涉及你不拥有的代码必须干净地删除,那么正确的方法是将代码放在它自己的进程中,而不是它自己的线程中.(最好是在该过程中高度安全性受限的应用程序域中.)然后,您可以彻底杀死该进程.

简而言之,Thread.Abort充其量只是表明设计糟糕,可能不可靠,而且非常危险.应该不惜一切代价避免; 你应该考虑中止线程的唯一一次是某种"紧急关闭"代码,你试图尽可能干净地拆除appdomain.

  • 在"约束执行区域"上进行网络搜索,您将了解到如何解决线程中止异常传播的问题. (8认同)

Dam*_*ver 17

因为如果您知道线程处于可以中止的安全状态,那么您肯定可以安排更好的通信并让线程干净地退出.

该线程可能已经锁定并且正在更改某些共享状态,并且Thread.Abort将撤消锁定并使共享状态损坏.


Qui*_*ome 13

伤害自己更容易.正如其他人所说,它在代码中引发了一个异常,它可以在任何时候发生.如果您期望这样,并且编码方式可以在任何时候优雅地处理此异常,但是有些人不会:

Monitor.Enter(obj);
// some code - if exception is raised here, then the lock isn't released
Monitor.Exit(obj)

IDisposable someCriticalResource = GetResource();
// some code - if exception is raised here, then the object isn't disposed
someCriticalResource.Dispose();
Run Code Online (Sandbox Code Playgroud)

此外,如果您与团队中的许多人合作,除非您有良好的代码审查,否则您无法保证您将使用的代码的质量.因此,传播"没有Thread.Abort()"的观点是一个好主意,而不是让人们记住编写对该代码中任何地方发生的异常具有鲁棒性的代码.

  • 这里重要的一点是`using`也不是*abort-safe - 在创建实例和`try-finally`块的开始之间有一个(微小的)机会窗口.这是一个很好的秘诀,你无法复制的细微错误,很容易破坏你的数据,挂起或杀死你的应用程序等. (5认同)

Vas*_*iak 7

简而言之.任何IDisposable对象都不得处置.任何锁定的对象都可能无法解锁.任何必须100%执行的事情永远不会完成.

  • 任何必须100%执行的操作迟早会因停电而失败... (11认同)
  • 这是不正确的,`Abort`将执行`finally`块,因此它将处理`IDisposable`也因为同样的原因释放任何锁. (6认同)
  • @SriramSakthivel:我很难做出这样的修正,但迟到总比没有好.**最后只有在输入try时才会运行块**.`使用(获取)体;`是`{获得; 试试{body} finally {dispose}}`.如果中止在获取步骤之后但在输入"try"之前发生了什么?或者更糟糕的是:如果获取步骤是`new Foo()`,构造函数打开文件句柄并将其分配给字段,该怎么办?**如果中止在开放之后但在分配之前发生了怎么办?这个答案绝对正确; 中止可导致一次性资源不受影响. (2认同)
  • @SriramSakthivel:另外,如果最终运行*,锁只会被释放*.在C#4之前,有可能在try块之前输入了监视器; 在C#4中,我们更改了codegen以防止这种可能性.但请记住,有些人在没有尝试的情况下编写监视器进入/退出对,我认为这实际上更安全; 中止确实可以导致监视器进入但从未退出.但这实际上并非坏事.坏的情况是我们输入一个锁,我们改变状态以违反一个不变量,线程在修复,解锁和暴露突变之前中止! (2认同)

Bri*_*sen 6

当您在另一个线程上调用 Thread.Abort() 时,会在该线程的流中注入 ThreadAbortException。如果你很幸运,代码会很好地处理这个问题并在一个明确定义的状态中中止。问题是您无法确定是否在每种情况下都很幸运,因此如果您更喜欢安全而不是抱歉在其他线程上调用 Thread.Abort 不是一个好主意。