C# 传递到已卸载AppDomain的服务内存泄漏
我在C# 传递到已卸载AppDomain的服务内存泄漏,c#,.net,memory-leaks,appdomain,C#,.net,Memory Leaks,Appdomain,我在AppDomains的上下文中遇到内存泄漏。我将其精简为以下内容: 我得到了3个项目,两个库项目和一个控制台项目:共享,dynamicallyadable和RemotingTimeoutPrototype(控制台程序)。共享包含dynamicallyadable和RemotingTimeoutPrototype使用的接口。两个引用在编译时共享。在任何项目之间都没有其他编译时引用 共享包含以下内容: public interface IHostService { string GetS
AppDomains
的上下文中遇到内存泄漏。我将其精简为以下内容:
我得到了3个项目,两个库项目和一个控制台项目:共享,dynamicallyadable
和RemotingTimeoutPrototype
(控制台程序)。共享包含dynamicallyadable
和RemotingTimeoutPrototype
使用的接口。两个引用在编译时共享。在任何项目之间都没有其他编译时引用
共享包含以下内容:
public interface IHostService
{
string GetStuff();
}
public interface IRemoteClass
{
IHostService Alpha { get; set; }
string CallHostServices();
}
DynamicallyLoaded仅包含一种类型:
public class RemoteClass : MarshalByRefObject, IRemoteClass
{
public IHostService Alpha { get; set; }
public string CallHostServices()
{
Console.WriteLine("Domain {0}, RemoteClass.CallHostServices():", AppDomain.CurrentDomain.Id);
return Alpha.GetStuff();
}
}
console项目包含IHostService
的实现:
public class Alpha : MarshalByRefObject, IHostService
{
readonly byte[] mBuffer = new byte[100*1024*1024];
public Alpha()
{
for (var i = 0; i < mBuffer.Length; ++i)
mBuffer[i] = (byte) (i%256);
}
public string GetStuff()
{
return "Alpha";
}
}
现在,当我让它运行一段时间后,内存消耗不断增加,最终我遇到了OutOfMemoryException
我希望,如果卸载了持有代理的域,那么代理也会被卸载,并且不再有对具体Alpha的引用,因此这将被收集。但显然不是这样
注意,我还通过引用mscoree并使用以下代码枚举加载的域,检查了域是否确实正在卸载:
var runtimeHost = new CorRuntimeHost();
runtimeHost.EnumDomains(out handle);
// etc.
另外,如果我将一个处理程序附加到otherDomain.DomainUnload(),则该处理程序的调用很好
有人能解释一下吗?这可能是一个典型的阻塞终结线程问题(正如您在while中循环,可能是STA线程,并且从不显式地将控制权交给其他线程)。即使卸载/处置域,它也可能位于内存中,因为它尚未完成。阅读更多内容:-特别是“阻止终结线程”部分(我是作者)我刚刚阅读了你的文章。明天我将按照您的描述使用WinDbg(现在我住的地方已经快凌晨2点了;)来检查是否在“准备完成”对象中看到任何构建。不过,我不知道我的情况会怎样。可能相关:while循环是我的Main所包含的,没有其他内容了。我只是尝试了一种更简单的方法来检查代理的RemoteClass实例是否正在被销毁,方法是向RemoteClass添加一个析构函数,如下所示:~RemoteClass(){Console.WriteLine(“正在销毁”);}-我看到控制台消息,因此代理实例正在被销毁。这将击败终结器理论,不是吗?我猜在这个线程中应该销毁/终结的不是RemoteClass,而是代理。无论如何,您是否尝试在GC.Collect之后添加WaitForPendingFinalizers?
var runtimeHost = new CorRuntimeHost();
runtimeHost.EnumDomains(out handle);
// etc.