Thread.Abort()方法冻结

时间:2013-12-11 13:39:00

标签: c# .net multithreading reflection appdomain

所以我用谷歌搜索它因为使用不安全的代码而冻结,并且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方式,它非常复杂。

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

1 个答案:

答案 0 :(得分:9)

这在设计上无法奏效。 CLR具有非常严格规则,可以安全地中止哪种代码。重要的是,除了不明智地使用Thread.Abort()之外,很多情况下CLR 必须中止代码,AppDomain卸载是最重要的。

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

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

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