在AppDomain中加载代码时出现严重内存泄漏
本文关键字:内存 泄漏 AppDomain 加载 代码 | 更新日期: 2023-09-27 18:23:43
我对正在处理的某些代码有一个不寻常的要求。我正在使用一个不可靠的第三方库来进行一些条形码扫描(运行太多次后就会停止工作)。为了解决这个问题,我决定在一个单独的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是一个静态方法,位于我的服务程序集中。
我对这个方法的问题是在某些地方内存泄漏。内存不断增长(当然,当调用此代码时),直到抛出OutOfMemoryException。
我哪儿也找不到漏洞。我所有的溪流都被处理掉了。我的所有字节数组都被清空了。我正在清理清单,所有过去对我有用的东西。我有大约90%的信心,泄漏与AppDomain的东西有关。这是我第一次使用它,所以我可能做错了什么。
我对AppDomains之外的另一种方法持开放态度。我确实需要从"Scanner"类返回结果的能力,所以生成进程不是一个选项。
AppDomain.Unload方法启动一个单独的线程来卸载域,该线程可能会由于各种原因而失败(执行非托管代码的线程是个问题)。以下是一个检查应用程序域是否已卸载的示例代码(取自msdn文档):
try
{
Console.WriteLine();
// Note that the following statement creates an exception because the domain no longer exists.
Console.WriteLine("child domain: " + domain.FriendlyName);
}
catch (AppDomainUnloadedException e)
{
Console.WriteLine("The appdomain MyDomain does not exist.");
}