Sun*_*nov 14 .net multithreading process appdomain finalizer
基于我的所有阅读,应该有一个GC线程来调用所有终结器.现在,问题是这个"一个"线程的范围是什么 - 每个进程或每个应用程序域,因为域的整个意图是在一个进程空间中分离并创建"独立"的不同应用程序.
我在这里读到:
如果在终结器中发生未处理的异常,则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");
}
}
Run Code Online (Sandbox Code Playgroud)
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);
};
}
}
Run Code Online (Sandbox Code Playgroud)
将每个编译为控制台应用程序,然后运行test.exe(从命令行最容易,IMO).您将看到一个应用程序域的终结器阻止另一个.
在将来,我不会惊讶地发现每个核心而不是每个AppDomain有一个终结器线程- 但听起来你仍然会遇到问题:(
你有最深切的同情(虽然不是解决方案) - 一旦我找到了Oracle Blob中的死锁.我们能够通过正确处理它来解决这个问题,但我知道并不是所有事情都能很好地完成 - 而且即使找到那个也真的很痛苦!