Thread.Abort() 方法冻结

Posted

技术标签:

【中文标题】Thread.Abort() 方法冻结【英文标题】:Thread.Abort() method freezes 【发布时间】:2013-12-11 13:39:00 【问题描述】:

所以我在谷歌上搜索到它由于使用了不安全的代码而冻结,并且 AbortException 仅在控制流返回到托管代码时才抛出。所以,就我而言,我有一个本地库,在线程中调用。所以有时我不能中止它,因为库是本机的,Abort 方法不仅什么都不做,而且冻结了调用线程。

所以,我想解决它。

例如,使用不同的流程应该会有所帮助,但它非常复杂。

因此,较轻的解决方案是使用 'AppDomains' 。但无论如何我应该创建一个exe并调用它。我试图像这样在内存中生成它

var appDomain = AppDomain.CreateDomain("newDomain");
var assemblyBuilder = appDomain.DefineDynamicAssembly(new AssemblyName("myAsm"), AssemblyBuilderAccess.RunAndCollect);
var module = assemblyBuilder.DefineDynamicModule("myDynamicModule");
var type = module.DefineType("myStaticBulder", TypeAttributes.Public);
var methBuilder = type.DefineMethod("exec", MethodAttributes.Static | MethodAttributes.Public);
var ilGenerator = methBuilder.GetILGenerator();

但是我发现只有EMIT-way,非常非常复杂。

是否存在肤浅的解决方案?

【问题讨论】:

看看ManualResetEvents 而不是Abort() 几乎任何您想查看的地方,即使线程纯粹在托管代码中运行,建议不要使用Thread.Abort 虽然这不能解决您的问题,但请不要使用Thread.Abort,而是查看正常退出的线程。 【参考方案1】:

这不能按设计工作。 CLR 非常严格地规定了可以安全地中止哪种代码。重要的是,除了不明智地使用 Thread.Abort() 之外,CLR 必须 中止代码的很多情况下,AppDomain 卸载是最重要的。

铁定的规则是,CLR 必须确信中止代码是安全。只有当线程忙于执行托管代码或正在等待托管同步对象时,才会确信这一点。您的案例符合条件,CLR 无法知道本机代码在做什么。在这种状态下中止线程几乎不会导致问题。对 Thread.Abort() 的危险的想法相同,但乘以一千。随后内部操作系统锁上的死锁很可能完全无法调试。

因此,AppDomain 也不是解决方案,它在线程停止运行之前无法卸载,并且不会。

您唯一能做的就是将该代码隔离在一个单独的进程中。编写一个小助手 EXE 项目,通过标准 .NET IPC 机制(如套接字、命名管道、内存映射文件、远程处理或 WCF)公开其 api。当代码挂起时,您可以安全地 Process.Kill() 它。不能造成任何损害,整个过程状态被丢弃。恢复往往非常棘手,但是,您仍然必须重新启动该过程并将其恢复到原始状态。尤其是状态恢复通常很难可靠地进行。

【讨论】:

以上是关于Thread.Abort() 方法冻结的主要内容,如果未能解决你的问题,请参考以下文章

可以像中止一个Thread(Thread.Abort方法)一样中止一个Task吗?

Thread.Abort 方法

.NET Thread.Abort 再次

c# .net 一条线程 abort 之后,怎么重启启动。

Thread.Abort() 并在 finally 之后延迟

Thread.Abort 的安全异常