2012-02-07 17 views
5

Tengo un requisito inusual para algún código en el que estoy trabajando. Estoy usando una biblioteca de terceros no confiable para hacer un escaneo de código de barras (deja de funcionar después de ejecutar demasiadas veces). Para evitar este problema, decidí hacer el trabajo en un Dominio de Aplicación separado y luego descargar el Dominio de la Aplicación cuando terminé. Esta es una imagen simplista, pero precisa, de lo que estoy haciendo:Fuga de memoria desagradable al cargar código en 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); 
} 

"escáner" es una clase contenedora alrededor de la biblioteca que estoy usando. Se sienta en el ensamblaje "Escaneo"; un proyecto separado solo para este propósito.

ScanningContext.DoWork es un método estático que se encuentra en el conjunto de mi servicio.

Mi problema con este método es que hay una pérdida de memoria en algún lugar. La memoria sigue creciendo y creciendo (cuando se llama este código, por supuesto) hasta que se lanzan OutOfMemoryExceptions.

No puedo encontrar la fuga en ningún lado. Todas mis transmisiones están siendo eliminadas. Todas mis matrices de bytes están siendo anuladas. Estoy borrando listas, todo lo que funcionó para mí en el pasado. Estoy casi 90% seguro de que la filtración está relacionada con este elemento de AppDomain. Esta es la primera vez que lo uso, así que probablemente estoy haciendo algo mal.

Estoy abierto a otro enfoque además de AppDomains. Necesito la capacidad de devolver resultados de la clase "Escáner", por lo que generar un proceso no es una opción.

+0

Dice que puede ejecutar el código de terceros al menos un par de veces. Entonces, ¿puede descartar la última incertidumbre del 10% comprobando si la filtración también existe sin usar los dominios de la aplicación? –

+2

Elimina el código de llamada del escáner, devuelve un resultado fijo y comprueba si la memoria sigue goteando, entonces aparece el problema de la aplicación, de lo contrario es el problema de la biblioteca de terceros ... –

+0

El método anterior consume mucha memoria, aproximadamente 250,000k cuando miro ahora, así que el uso de la memoria no es bueno. Sin embargo, no se ha quedado sin memoria como lo está haciendo mi nuevo enfoque. Entonces, para responder a su pregunta, no, no puedo descartar el otro 10%, tuve que reescribir un poco de código para usar AppDomains, así que podría haber introducido la fuga en ese momento. – Matthew

Respuesta

2

El método AppDomain.Unload inicia un hilo separado para descargar el dominio, que puede fallar por varios motivos (los hilos que ejecutan el código no administrado son un problema). Aquí hay un código de muestra que comprueba si el dominio de la aplicación está descargado (tomado de msdn documentos):

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