2012-02-07 3 views
5

У меня есть необычное требование для некоторого кода, над которым я работаю. Я использую ненадежную стороннюю библиотеку для сканирования некоторых штрих-кодов (она перестает работать после запуска слишком много раз). Чтобы обойти эту проблему, я решил сделать работу в отдельном 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); 
} 

«Сканер» класс обертку вокруг библиотеки, я использую. Он находится в сборке «Сканирование»; отдельный проект для этой цели.

ScanningContext.DoWork - это статический метод, который находится на моей службе.

Проблема с этим методом заключается в том, что там есть утечка памяти. Память продолжает расти и возрастать (когда этот код называется, конечно), пока не будут выбраны OutOfMemoryExceptions.

Я не могу найти утечку где угодно. Все мои потоки расположены. Все мои байтовые массивы обнуляются. Я расчищаю списки, все, что сработало для меня в прошлом. Я почти на 90% уверен, что утечка связана с этим продуктом AppDomain. Это мой первый раз, когда я использую его, поэтому я, вероятно, что-то делаю неправильно.

Я открыт для другого подхода, кроме AppDomains. Мне нужна способность возвращать результаты из класса «Сканер», поэтому нереста процесса не является вариантом.

+0

Вы говорите, что вы можете запустить сторонний код хотя бы пару раз. Так вы можете исключить последнюю 10% -ную неопределенность, проверяя, существует ли утечка без использования доменов приложений? –

+2

Удалите код вызова сканера, верните фиксированный результат и проверьте, нет ли утечки памяти, а затем его проблема с appDomain, в противном случае проблема со сторонней библиотекой. –

+0

Старый метод потребляет много памяти, около 250 000 000, поскольку я смотрю на это сейчас, так что использование памяти не очень хорошо. Однако он не исчерпывает память, как мой новый подход. Поэтому, чтобы ответить на ваш вопрос, я не могу исключить других 10%, мне пришлось переписать немного кода для использования AppDomains, чтобы я мог ввести утечку в это время. – Matthew

ответ

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."); 
} 
Смежные вопросы