【问题标题】:Is Thread.Abort() corruption localized?Thread.Abort() 损坏是否已本地化?
【发布时间】:2010-07-14 08:02:48
【问题描述】:

我了解由于各种原因调用 Thread.Abort() 是错误的

  1. 可以锁定或处于其他关键区域
  2. 可能正在进行 I/O 操作,资源不会被清理
  3. 代码可以吞下 ThreadAbortException
  4. 可能正在进行状态更改操作,并使程序处于无效状态。

假设线程的Run()方法:

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

问题:

如果我要在这样的线程上调用 Abort(),造成的损害(关于损坏)是否已本地化?如在,我可以依靠我的程序,没有最近中止的线程,继续正常运行,还是我的整个进程/AppDomain/?那么可能已损坏?

如果我删除假设 1 和 2,abort() 损坏是否会本地化到它访问的特定并发原语和 i/o 资源?还是可以向外传播?

我为什么要鞭打 Thread.Abort() 死马

我正在编写一个胖客户端 c# winforms 应用程序。一个功能是用户可以在 c# 中编写代码,该代码在我的域对象上实现接口,然后可以将其插入我的应用程序(代码通过 codedom 编译成程序集并使用反射加载);

所以这个想法是用户可以写

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

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

问题在于,用户可以编写上面的内容——一个无限循环,或者他决定不想等待的其他指数时间计算。

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

【问题讨论】:

  • 嗯,即使 Abort 也不一定真的会中止(可以被阻止,正如你所提到的)。假设您想跳过更复杂的事情(例如,单独的 AppDomain),那么更简单的事情是:1)在启动线程之前将线程设置为后台 2)如果您决定它“失控”,您可以 Abort() 它,但是您也可以决定将优先级降到最低并保持不变:)

标签: c# .net multithreading


【解决方案1】:

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

事实上,从 .Net 3.5 开始,.Net 框架就包含了 System.AddIn 命名空间,它提供了一种在单独的应用程序域中隔离“插件”代码的简化方法(除其他外)。如果不需要太多的跨域通信,这会给你一个很好的隔离级别,最坏的情况是你拆除了一个特定于用户代码的 AppDomain。

请参阅这篇MSDN 文章和CLR-Addin team's blog 了解更多信息。

此外,虽然它不能解决所有问题,但您可以从触发 Thread.Interrupt 开始。这将导致 ThreadInterruptException 以与 ThreadAbortException 类似的方式引发,除了它只会在代码中的定义点发生;当线程阻塞或休眠时,而不是绝对在任何地方。在您上面提到的紧密循环示例中它可能无济于事,但如果循环具有 Thread.Sleep(0) 则会有帮助。

你总是可以毕业你的选择:

  • 在 IComputationThing 上放置一个 Stop() 方法并要求用户实现它。
  • 如果加载项未及时响应 Stop(),请尝试 Thread.Interrupt(并记录紧循环者可能希望在其循环中放置 Thread.Sleep(0) 以让步另一个线程)
  • 如果失败,请尝试 Thread.Abort,或拆除 App Domain(可能直接拆除后者)。

【讨论】:

    【解决方案2】:

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

    如果您使用生成的代码,单独的AppDomain 更容易停止和卸载,并且与线程不同,这可以作为托管进程正常生命周期的一部分来完成。

    【讨论】:

      【解决方案3】:

      Thread.Abort() 肯定会污染您的 AppDomain,但我相信它也会破坏整个进程的稳定性。我这么快就找不到链接了。

      因此,您必须在单独的(一次性)进程中运行它。

      【讨论】:

        【解决方案4】:

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

        现在,我实际上开始想知道如果用户代码会产生另一个线程/应用程序域会发生什么,但这是另一个问题。也许可以通过一些权限来解决,我对这些不是很熟悉。

        【讨论】:

          【解决方案5】:

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

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

          http://terrarium2.codeplex.com/

          【讨论】:

            猜你喜欢
            • 2011-10-29
            • 1970-01-01
            • 2011-10-29
            • 2017-04-06
            • 1970-01-01
            • 1970-01-01
            • 2014-12-17
            • 2012-04-13
            • 1970-01-01
            相关资源
            最近更新 更多