在 AppDomain 中加载代码时出现严重的内存泄漏
我对我正在处理的一些代码有一个不寻常的要求。我正在使用不可靠的第三方库来进行一些条形码扫描(运行太多次后它会停止工作)。为了解决这个问题,我决定在单独的 AppDomain 中完成工作,然后在完成后卸载 AppDomain。这是我正在做的事情的简单但准确的描述:
string domainID = Guid.NewGuid().ToString();
AppDomainSetup setup = new AppDomainSetup();
AppDomain domain = AppDomain.CreateDomain(domainID, null, setup);
string result = null;
try
{
domain.SetData("stream", stream);
domain.DoCallBack(ScanningContext.DoWork);
result = domain.GetData("result") as string;
}
finally
{
AppDomain.Unload(domain);
}
return result;
public static void DoWork()
{
Stream s = AppDomain.CurrentDomain.GetData("stream") as Stream;
ObjectHandle handle = AppDomain.CurrentDomain.CreateInstance("Scanning",
"Scanner");
Scanning.Scanner scanner = (Scanning.Scanner)handle.Unwrap();
Scanning.Result[] results = scanner.Scan(s);
AppDomain.CurrentDomain.SetData("result", results[0].Text);
}
“Scanner”是我正在使用的库的包装类。它位于“扫描”组件中;一个单独的项目就是为了这个目的。
ScanningContext.DoWork 是位于我的服务程序集中的静态方法。
我使用此方法的问题是某些地方存在内存泄漏。内存不断增长(当然,当调用此代码时),直到抛出 OutOfMemoryExceptions。
我找不到任何地方有泄漏。我所有的流都被处理掉了。我的所有字节数组都被清空。我正在清理清单,清理过去对我有用的一切。我大约有 90% 的信心认为此次泄漏与 AppDomain 相关。这是我第一次使用它,所以我可能做错了什么。
我对 AppDomains 之外的另一种方法持开放态度。我确实需要能够从“Scanner”类返回结果,因此不能选择生成进程。
I have an unusual requirement for some code I am working on. I'm using an unreliable 3rd party library to do some barcode scanning (it stops working after running too many times). To get around this problem I decided to do the work in a separate AppDomain and then to unload the AppDomain when I am finished. This is a simplistic, but accurate, picture of what I am doing:
string domainID = Guid.NewGuid().ToString();
AppDomainSetup setup = new AppDomainSetup();
AppDomain domain = AppDomain.CreateDomain(domainID, null, setup);
string result = null;
try
{
domain.SetData("stream", stream);
domain.DoCallBack(ScanningContext.DoWork);
result = domain.GetData("result") as string;
}
finally
{
AppDomain.Unload(domain);
}
return result;
public static void DoWork()
{
Stream s = AppDomain.CurrentDomain.GetData("stream") as Stream;
ObjectHandle handle = AppDomain.CurrentDomain.CreateInstance("Scanning",
"Scanner");
Scanning.Scanner scanner = (Scanning.Scanner)handle.Unwrap();
Scanning.Result[] results = scanner.Scan(s);
AppDomain.CurrentDomain.SetData("result", results[0].Text);
}
"Scanner" is a wrapper class around the library I'm using. It sits in the "Scanning" assembly; a separate project just for this purpose.
ScanningContext.DoWork is a static method that sits in my service's assembly.
My problem with this method is that there is a memory leak some where. Memory keeps growing and growing (when this code is called, of course) until OutOfMemoryExceptions are thrown.
I can't find the leak any where. All of my streams are being disposed. All of my byte arrays are being nulled. I'm clearing lists, everything that has worked for me in the past. I'm about 90% confident that the leak is related to this AppDomain stuff. This is my first time using it so I'm probably doing something wrong.
I'm open to another approach besides AppDomains. I do require the ability to return results from the "Scanner" class, so spawning a process is not an option.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
AppDomain.Unload 方法启动一个单独的线程来卸载域,该线程可能会因各种原因而失败(执行非托管代码的线程是一个问题)。以下是检查应用程序域是否已卸载的示例代码(取自 msdn 文档):
The AppDomain.Unload method starts a separate thread to unload the domain, which may fail for various reasons (threads executing unmanaged code is a problem). Here is a sample code that checks if the app domain is unloaded (taken from msdn docs):