在AppDomain中加载代码时出现令人讨厌的内存泄漏

时间:2012-02-07 14:09:45

标签: c# 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之外的另一种方法持开放态度。我确实需要能够从“扫描仪”类返回结果,因此不能选择产生一个过程。

1 个答案:

答案 0 :(得分:2)

AppDomain.Unload方法启动一个单独的线程来卸载域,这可能由于各种原因而失败(执行非托管代码的线程是个问题)。下面是一个示例代码,用于检查应用程序域是否已卸载(取自msdn docs):

 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.");
 }