代码之家  ›  专栏  ›  技术社区  ›  fostandy

thread.abort()是否本地化损坏?

  •  1
  • fostandy  · 技术社区  · 15 年前

    我知道调用thread.abort()是错误的,原因有很多

    1. 可以锁定或在其他关键区域
    2. 可能在I/O操作的中途,资源不会被清除。
    3. 代码可以吞咽threadabortexception
    4. 可能处于状态更改操作的中间,并使程序处于无效状态。

    假设线程的run()方法:

    1. 不使用并发原语。
    2. 不执行任何I/O。
    3. 不接受这种例外。
    4. 暴露于只读API,因此无法更改程序状态。

    问题:

    如果我要在这样的线程上调用abort(),那么损坏是否已本地化(与损坏有关)?如中所述,我可以依靠我的程序(sans是最近中止的线程)继续正常运行吗,还是我的整个进程/appdomain/??然后可能被破坏?

    如果我删除假设1和假设2,abort()是否将损坏本地化为它访问的特定并发原语和I/O资源?或者它能向外支撑吗?

    为什么我要鞭打线程。abort()死马 :

    我正在编写一个厚客户端C WinForms应用程序。一个特点是,用户可以用C语言编写代码,C语言在我的域对象上实现接口,然后将接口插入我的应用程序(代码通过codedom编译到程序集中,并通过反射加载);

    所以用户可以写

    public class CustomComputation : IComputationThing
    {
        public void Compute(object context)
        {
            while (true) ;
        }
    }
    

    然后我可以反思生成的程序集,提取并实例化 CustomComputation 和呼叫 Compute(...); 非常简单的东西。

    问题是,用户可以写上面的内容——一个无限循环,或者其他一些他认为不想等待的指数时间计算。

    我正在尝试研究我的选项,当用户编写一些无限循环(或指数时间等)代码并希望从中中止时,可以为其提供尽最大努力的恢复。虽然我确实打算要求用户坚持取消模式,但最终并不能保证他们会这样做。

    5 回复  |  直到 15 年前
        1
  •  1
  •   Rob Levine    15 年前

    正如Vilx提到的,您可以考虑将“用户”代码放在另一个AppDomain中。

    实际上,自.NET 3.5以来,.NET框架已经包含了 System.AddIn 名称空间,它提供了一种在单独的应用程序域中隔离“外接程序”代码的简化方法(除其他外)。如果不需要太多的跨域通信,那么这将为您提供一个很好的隔离级别,在这种情况下,最坏的情况是您删除了一个特定于用户代码的AppDomain。

    看到这个 MSDN 文章和 CLR-Addin team's blog 更多信息。

    另外,尽管它并不能解决所有问题,但您可以从触发一个thread.interrupt开始。这将导致以与ThreadAbortException类似的方式引发ThreadInterruptException,但它将在代码中定义的点上发生;当线程阻塞或休眠时,而不是绝对在任何位置发生。在上面提到的紧循环示例中,它可能不会有所帮助,但如果循环有线程,它会有所帮助。sleep(0)。

    你可以选择毕业:

    • 在IComputationThing上放置stop()方法,并要求用户实现它。
    • 如果外接程序没有及时响应stop(),请尝试使用thread.interrupt(并记录紧密循环程序可能希望在其循环中放入thread.sleep(0)以生成另一个线程)
    • 如果失败,请尝试thread.abort,或者关闭应用程序域(可能是后者直接)。
        2
  •  1
  •   Pontus Gagge    15 年前

    除非您对.NET运行库的每一个细节都很了解,否则我怀疑您是否能够真正保证您的假设(尤其是4和1)。违反假设4所需要的只是一个静态变量…

    如果使用生成的代码,则 AppDomain 更容易停止和卸载,与线程不同,这可以作为宿主进程正常生命周期的一部分完成。

        3
  •  1
  •   Henk Holterman    15 年前

    thread.abort()肯定会污染您的AppDomain,但我相信它也会破坏整个过程。我找不到这么快的链接。

    所以你必须在一个单独的(一次性的)过程中运行它。

        4
  •  1
  •   Vilx-    15 年前

    由于用户代码是动态的(我希望典型的开发人员在编写代码时会进行几十次测试运行),所以您无论如何都要将它放在单独的AppDomain中,以便卸载它。如果是这样,则损坏将只影响单独的AppDomain,它将很快卸载。

    现在,我开始怀疑如果用户代码产生另一个线程/AppDomain会发生什么,但这是另一个问题。也许它可以通过一些权限来解决,我对这些完全不熟悉。

        5
  •  1
  •   user180326    15 年前

    看看.NET Terrium项目。这是一个对等演示应用程序,旨在演示.NET框架的对等功能和黑客安全性。开发人员可以匿名编写和上传人工智能代码,以控制在数千台机器上作为点对点生态系统运行的虚拟环境中的昆虫。

    他们使用反射来确保上传的代码是安全的:你不能做IO,锁是受限制的,还有静态变量。他们也限制了你被允许“思考”的时间。对这个应用程序来说足够好的东西对你来说应该足够好。

    http://terrarium2.codeplex.com/