2012-02-07 9 views
5

Üzerinde çalıştığım bazı kodlar için sıra dışı bir gereksinim var. Bazı barkod tarama yapmak için güvenilmez bir 3. parti kitaplığı kullanıyorum (çok fazla çalıştırdıktan sonra çalışmayı durdurur). Bu sorunu aşmak için, işi ayrı bir AppDoma alanında yapmaya karar verdim ve sonra bitirdiğimde AppDomain'i boşaltmaya karar verdim.AppDomain'de kod yüklerken kötü bellek sızması

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

"Tarayıcı" Ben kullanıyorum kütüphaneye etrafında sarıcı sınıftır: Bu ne yaptığımı bir, basit ama doğru resimdir. "Tarama" tertibatında oturur; Sadece bu amaç için ayrı bir proje.

ScanningContext.DoWork, hizmet bölümümde bulunan statik bir yöntemdir.

Bu yöntemdeki sorunum, bir miktar bellek sızıntısı olmasıdır. Bellek OutOfMemoryExceptions atılır kadar büyüyen ve büyüyen (bu kod çağrıldığında, elbette) devam ediyor.

Sızıntıyı herhangi bir yerde bulamıyorum. Bütün akımlarım bertaraf ediliyor. Tüm bayt dizilerim siliniyor. Listeleri temizliyorum, geçmişte benim için çalışan her şey. Sızıntının bu AppDomain nesnesiyle ilgili olduğundan yaklaşık% 90 eminım. Bu benim ilk kez kullanıyorum, bu yüzden muhtemelen yanlış bir şey yapıyorum.

AppDomains dışındaki başka bir yaklaşıma açığım. "Tarayıcı" sınıfından sonuçlar döndürme yeteneğine ihtiyacım var, bu yüzden bir süreç oluşturmak bir seçenek değildir.

+0

En az birkaç kez üçüncü taraf kodunu çalıştırabileceğinizi söylüyorsunuz. Bu nedenle, uygulama alanlarını kullanarak sızıntının mevcut olup olmadığını kontrol ederek son% 10 belirsizliğini göz ardı edebilirsiniz? –

+2

Tarayıcı çağırma kodunu kaldırın, sabit bir sonuç döndürün ve belleğin hala oradan onun appDomain sorunu olup olmadığını kontrol edin, aksi takdirde 3. taraf kitaplığı sorunu .. –

+0

Eski yöntem, baktığımda yaklaşık 250.000 bin bellek harcar. şimdi, bu yüzden hafıza kullanımı iyi değil. Ancak yeni yaklaşımımın yaptığı gibi hafıza bitmemişti. Bu nedenle, sorunuzu cevaplamak için, diğer% 10'u göz ardı edemem, AppDomains'i kullanmak için biraz kod yazmak zorunda kaldım, böylece o zamanki sızıntıyı tanıtabilirdim. – Matthew

cevap

2

AppDomain.Unload yöntemi, farklı nedenlerden dolayı başarısız olabilecek etki alanını kaldırmak için ayrı bir iş parçacığı başlatır (yönetilmeyen kod yürüten iş parçacıkları bir sorundur). Burada uygulama etki alanının kaldırıldığını kontrol eden bir örnek kod (msdn belgelerinden alınmıştır):

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