所以我知道你不应该使用
Thread.Abort()
但是我从来没有得到很好的解释。是否有性能损失或一些隐患?
我知道您不能忽略/吞咽ThreadAbortException(这很有意义)
Answers:
除了这里所有其他好的答案之外,让我补充一点,这不能保证对Thread.Abort的调用实际上会永远终止所讨论的线程。有可能(尽管不是特别容易)“加固”线程以防线程中止。例如,如果您因为认为线程正在运行恶意代码而中止了线程,那么恶意代码可能会抵制自己的破坏。
如果您有长时间运行的涉及不属于您的代码的操作,必须将其彻底删除,那么正确的方法是将该代码放入自己的进程中,而不是放在自己的线程中。(最好是在该过程中受高度安全性限制的应用程序域中。)然后,您可以清除该过程。
简而言之,Thread.Abort最多表示不良设计,这可能是不可靠的,并且非常危险。应不惜一切代价避免这种情况;您甚至应该考虑中止线程的唯一时间是某种“紧急关闭”代码,在该代码中,您试图尽可能干净地关闭应用程序域。
AppDomain.Unload
用来拆除应用程序域吗?AppDomain.Unload
将为您调用Thread.Abort
域中运行的所有线程。
Thread.Abort
它是为了避免CannotUnloadAppDomainException
中止需要花费一些时间。通过使用Thread.Abort
,您可以等待线程真正中止,然后再调用AppDomain.Unload
。
因为如果您知道线程处于可以退出的安全状态,那么可以肯定地可以安排更好的通信并让线程干净退出。
线程可能已经锁定并且处于更改某些共享状态的中间,并且Thread.Abort将撤消该锁定并使共享状态损坏。
Abort
可能发生的任何地方(在托管代码) -即使lock
语句本身实际上是不放弃安全。因此,您不仅可能处于损坏状态,而且实际上可能lock
无法释放它-当然,该线程将在线程死亡时被释放,但实际上并不需要发生(直到该过程为止)死亡)。
finally
可以正确处理所有内容的子句吗?当然,通过避免共享状态,而仅在安全,受约束的区域中更新共享状态,可以使工作变得更加容易……但是,您现在已经可以不需要显式共享状态了。
伤害自己更容易。正如其他人所说,它在代码中引发了一个异常,该异常可能在任何时候发生。如果您期望这样做并且以某种方式可以随时优雅地处理此异常的方式进行了编码,但有些人却没有,那就可能很好:
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();
此外,如果您与团队中的许多人一起工作,除非您对代码进行了良好的审查,否则您不能保证将使用的代码的质量。因此,鼓吹“ no Thread.Abort()”的福音是一个好主意,而不是让人们记住编写针对该代码中任何地方发生的异常情况都健壮的代码。
using
是不中止安全-在创建实例和try-finally
块的开始之间有一个(很小的)机会窗口。它是微妙的错误的一大秘方,你将永远不会成为能够重现,并且可以很容易地破坏你的数据,挂或杀死你的应用程序等等
简而言之。不可丢弃任何IDisposable对象。任何锁定的对象都可能无法解锁。任何必须100%执行的操作将永远不会完成。
Abort
将执行finally
块,因此将IDisposable
由于相同的原因也将释放所有锁。
finally
将运行。不管您是否使用using
语句。
using(acquire) body;
是{ acquire; try { body } finally { dispose }}
。如果中止发生在获取步骤之后但try
输入之前呢?或者,更糟糕的是:如果获取步骤是new Foo()
在构造函数中打开文件句柄并将其分配给字段的方法,那该怎么办?如果中止发生在公开赛之后但分配前呢?这个答案是绝对正确的。中止会导致可处置资源无法处置。
Thread.Abort以不受控制的方式停止线程。thread.Abort将引发异常,这将导致您的线程立即停止。
这是怎么回事:在大多数情况下,您希望适当地停止正在执行的操作。例如,如果您正在执行ACID操作,则可能要在结束线程之前完成当前操作,以使系统保持稳定状态。
Thread.Abort在目标线程中引发异常。同时,目标线程可能正在执行某些关键操作,而引发异常可能会破坏您的应用程序状态。