终结器线程的范围是什么 - 每个应用程序域或每个进程?

2024-05-15

根据我的所有阅读,应该有一个 GC 线程来调用所有终结器。现在的问题是这个“一个”线程的范围是什么 - 每个进程或每个应用程序域,因为域的整体目的是在一个进程空间中分离并创建“独立”的不同应用程序。

I read here http://dn.codegear.com/article/29365#MoreFinalizerIssues:

如果未处理的异常发生在 CLR 执行线程的终结器 将吞掉异常,治疗 终结器就像正常完成一样, 将其从脆弱队列中删除 并移至下一个条目。

但更严重的是,发生的事情 如果你的终结器没有退出 某些原因,例如它阻止, 等待一个永远不会发生的条件 发生。在这种情况下,终结器 线程将被挂起,所以不再有 可终结的对象将是垃圾 集。你应该非常 意识到这种情况并坚持 编写最简单的代码来释放你的 终结器中的非托管资源。

另一个考虑因素是会发生什么 在应用程序关闭期间。当。。。的时候 程序关闭,垃圾收集器 将尽力调用终结器 所有可终结的对象,但是 某些限制:

  • 可终结的对象不会被提升 到更高的堆代 关闭。

  • 任何单独的终结器都会有一个 最多执行 2 秒;如果它 时间再长就会被杀死。

  • 最多有 40 秒的时间 所有要执行的终结器;如果有的话 终结器仍在执行,或者 此时待全部 进程突然被终止。

太多的帖子(甚至官方文档)滥用了术语“应用程序”、“进程”和“应用程序域”——其中大多数甚至假设它们是相等的,因为应用程序通常在单个进程的单个应用程序域中运行。这种滥用使得所有这些文档都难以阅读,甚至没有用处。

因此,我的问题假设有多个应用程序,每个应用程序在单个进程的单独应用程序域中运行。

所有这些应用程序是否共享相同的 GC 和终结器线程?上面文章中描述的问题(挂起终结器线程)是否会影响该进程中的所有应用程序?如果是 - 是否有解决方法(除了不使用不良应用程序之外),例如以某种方式发现终结器线程并将其发送 Thread.Abort?

以上都是因为我遇到了类似的问题。我的应用程序作为第三方软件(Outlook)的插件在单独的应用程序域中运行。由于各种原因,我需要调用 GC.Collect 和 GC.WaitForPendingFinalizers 来完全释放 COM 引用(通常的互操作例程对于 Office/Outlook 来说是不够的),当特定的其他第三方插件正在运行时,我的 GC.WaitForPendingFinalizers 永远挂起,所以我怀疑第三方添加中有一个“坏”终结器。我无法控制替换/删除该添加(客户的要求),所以我必须自己弄清楚如何使它们共存。


看起来,进程中的每个 CLR 实例确实只有一个线程——无论如何,目前是这样。下面是一些代码来表明:

Test.cs:

using System;

class Test
{
    static void Main()
    {
        AppDomain.CreateDomain("First")
                 .ExecuteAssembly("ShowFinalizerThread.exe");
        AppDomain.CreateDomain("Second")
                 .ExecuteAssembly("ShowFinalizerThread.exe");
    }
}

ShowFinalizerThread.cs:

using System;
using System.Threading;

class ShowFinalizerThread
{
    static Random rng = new Random();

    ~ShowFinalizerThread()
    {
        Console.WriteLine("Thread/domain: {0}/{1}",
                          Thread.CurrentThread.ManagedThreadId,
                          AppDomain.CurrentDomain.FriendlyName);
        if (rng.Next(10) == 0)
        {
            Console.WriteLine("Hanging!");
            Thread.Sleep(2000);
        }
    }

    static void Main()
    {
        new Thread(LoopForever).Start();
    }

    static void LoopForever()
    {
        while (true)
        {
            new ShowFinalizerThread();
            GC.Collect();
            GC.WaitForPendingFinalizers();
            Thread.Sleep(300);
        };
    }
}

将每个程序编译为控制台应用程序,然后运行 ​​test.exe(在我看来,从命令行是最简单的)。您将看到一个应用程序域的终结器阻止了另一个应用程序域的终结器。

将来,如果每个线程都有一个终结器线程,我不会感到惊讶core而不是每个 AppDomain - 但听起来你仍然会遇到问题:(

当我在 Oracle Blob 中发现死锁时,我对您表示最深切的同情(尽管不是解决方案)。我们能够通过正确处理它来解决这个问题,但我知道并不是所有的东西都能很好地工作 - 即使找到它也是一种真正的痛苦!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

终结器线程的范围是什么 - 每个应用程序域或每个进程? 的相关文章

  • 在一个数据访问层中处理多个连接字符串

    我有一个有趣的困境 我目前有一个数据访问层 它必须与多个域一起使用 并且每个域都有多个数据库存储库 具体取决于所调用的存储过程 目前 我只需使用 SWITCH 语句来确定应用程序正在运行的计算机 并从 Web config 返回适当的连接字
  • C# xml序列化必填字段

    我需要将一些字段标记为需要写入 XML 文件 但没有成功 我有一个包含约 30 个属性的配置类 这就是为什么我不能像这样封装所有属性 public string SomeProp get return someProp set if som
  • 如何在 Linq to SQL 中使用distinct 和 group by

    我正在尝试将以下 sql 转换为 Linq 2 SQL select groupId count distinct userId from processroundissueinstance group by groupId 这是我的代码
  • 用于运行可执行文件的python多线程进程

    我正在尝试将一个在 Windows 上运行可执行文件并管理文本输出文件的 python 脚本升级到使用多线程进程的版本 以便我可以利用多个核心 我有四个独立版本的可执行文件 每个线程都知道要访问它们 这部分工作正常 我遇到问题的地方是当它们
  • C# 中的 IPC 机制 - 用法和最佳实践

    不久前我在 Win32 代码中使用了 IPC 临界区 事件和信号量 NET环境下场景如何 是否有任何教程解释所有可用选项以及何时使用以及为什么 微软最近在IPC方面的东西是Windows 通信基础 http en wikipedia org
  • Interlocked.CompareExchange 的返回值是否有一些充分的理由

    The Interlocked CompareExchange 方法 docs https learn microsoft com en us dotnet api system threading interlocked comparee
  • NuGet:包含 .pdb 文件并排除“Content”文件夹

    我已将以下行合并到 CI 构建中在每个构建上创建一个私有 NuGet 包 nuget pack C Projects Test Test vbproj OutputDirectory nas1 NuGet The 读取AssemblyInf
  • 比较已编译的 .NET 程序集?

    有没有什么好的程序可以与编译 NET 程序集进行比较 例如 我有 HelloWorld dll 1 0 0 0 和 HelloWorld dll 2 0 0 0 我想比较差异 我该怎么做 我知道我可以使用 NET Reflector 并使用
  • 优化计算中使用的 # 个线程的算法

    我正在执行一个操作 我们将其称为CalculateSomeData CalculateSomeData 在连续的 代 中运行 编号为 1 x 整个运行中的代数由CalculateSomeData 的输入参数固定 并且是先验已知的 完成一次生
  • 为什么 C# 不支持类构造函数中的隐式泛型类型?

    如果编译器可以推断出泛型类型参数 C 并不要求您指定它 例如 List
  • 进度条没有进展

    我有一个正在更新 sqlserver 中的表的程序 我有一个表单 我想显示其进度 进度条正在递增 但没有显示 我需要为此使用后台工作者吗 我正在做什么的例子 public void updateTable string tableName
  • 为什么 i++ 不是原子的?

    Why is i Java 中不是原子的 为了更深入地了解 Java 我尝试计算线程中循环的执行频率 所以我用了一个 private static int total 0 在主课中 我有两个线程 主题 1 打印System out prin
  • 如何计算最低系统要求?

    对于我用 Visual C 编写的应用程序 Testing 不 真的 这就是全部
  • 什么时候值得使用 BindingSource?

    我想我非常了解 BindingSource 类的作用 即在数据源和 UI 控件之间提供一个间接层 它实现了 IBindingList 接口 因此还提供了对排序的支持 而且我已经经常使用它 没有太多问题 但我想知道我使用它的频率是否超过了应有
  • 没有强命名的代码签名是否会让您的应用程序容易被滥用?

    尝试了解authenticode代码签名和强命名 我是否正确地认为 如果我对引用一些 dll 非强命名 的 exe 进行代码签名 恶意用户就可以替换我的 DLL 并以看似由我签名但正在运行的方式分发应用程序他们的代码 假设这是真的 那么您似
  • 临时表是线程安全的吗?

    我正在使用 SQL Server 2000 它的许多存储过程广泛使用临时表 数据库的流量很大 我担心创建和删除临时表的线程安全性 假设我有一个存储过程 它创建了一些临时表 它甚至可以将临时表连接到其他临时表等 并且还可以说两个用户同时执行存
  • 无锁算法真的比全锁算法性能更好吗?

    陈雷蒙德 http blogs msdn com b oldnewthing 一直在做一个huge http blogs msdn com b oldnewthing archive 2011 04 15 10154245 aspx ser
  • 垃圾收集器是否在单独的进程中运行?

    垃圾收集器是否在单独的进程中启动 例如 如果我们尝试测量某段代码所花费的进程时间 并且在此期间垃圾收集器开始收集 它会在新进程上启动还是在同一进程中启动 它的工作原理如下吗 Code Process 1 gt Garbage Collect
  • 如何使用 C# / .Net 将文件列表从 AWS S3 下载到我的设备?

    我希望下载存储在 S3 中的多个图像 但目前如果我只能下载一个就足够了 我有对象路径的信息 当我运行以下代码时 出现此错误 遇到错误 消息 读取对象时 访问被拒绝 我首先做一个亚马逊S3客户端基于我的密钥和访问配置的对象连接到服务器 然后创
  • Windows 和 Linux 上的线程

    我在互联网上看到过在 Windows 上使用 C 制作多线程应用程序的教程 以及在 Linux 上执行相同操作的其他教程 但不能同时用于两者 是否存在即使在 Linux 或 Windows 上编译也能工作的函数 您需要使用一个包含两者的实现

随机推荐