2012-10-31 17 views
10

Jeśli mam aplikację konsoli z kodu, takich jak:Wywołanie Environment.Exit() wewnątrz bloku Using

using (DisposableObject object = new DisposableObject()) 
{ 
    if (a condition) 
    Environment.Exit(0); 

    // Do Stuff 
} 

Czy mój obiekt jest prawidłowo umieszczony? Czy wątek umiera przed oczyszczeniem obiektu?

+0

Należy pamiętać, że jeśli zamkniesz aplikację, nawet jeśli obiekt nie jest Utylizowany, nie będzie faktycznie wyciekać pamięci (ponieważ proces chroniony pamięci jest całkowicie wolny po zakończeniu procesu.) Inne rzeczy mogą pójść źle jeśli Disposal ma bardziej trwałe skutki uboczne (takie jak popełnienie błędu w bazie danych lub coś, co żyje poza zakresem procesu). –

+1

@DanBryant niewydany zasób nie wyciek * zarządzanej * pamięci. Jeśli niezainstalowany zasób jest niezarządzaną pamięcią (prawdopodobnie z powodu interopu z niezmienionym językiem), możesz mieć niewydaną pamięć. – Servy

+0

Używam go na 'SqlConnection', ale blok' using' jest zagnieżdżony w dwóch innych (obiektach SharePoint). Po prostu chciałem się upewnić, że metody "Dispose()" zostaną wywołane, ponieważ nie pozbycie się obiektów SP generuje błędy w dziennikach. –

Odpowiedz

9

Twoja aplikacja zostanie zakończona, a cała zarządzana pamięć zostanie zwolniona w tym momencie.

Wygenerowany blok finally nie zostanie wykonany, więc wszelkie metody Dispose nie będą wywoływane, więc wszelkie niezarządzane zasoby mogą nie zostać zwolnione.

Zobacz Don't Blindly Count on a Finalizer.

+0

Czy zostałby wykonany kod '// Do Stuff'? Co dokładnie robi "Environment.Exit (0); –

+0

'// Do Stuff' nie zostanie wykonany. 'Environment.Exit (0)' zabija wątek i zwraca 0 z głównego. –

+0

@ OlivierJacot-Descombes - '// Do Stuff' nie zostanie wykonany. Wywołanie po prostu kończy proces (zwracając kod błędu - przekazany w 'int'). – Oded

1

Zasoby, o których wie system operacyjny, zostaną ogólnie wyczyszczone po wyjściu aplikacji. Zasoby, o których system operacyjny nie wie, zazwyczaj nie będą oczyszczane.

Na przykład niektóre programy korzystające z bazy danych i wymagające implementacji paradygmatu blokowania różniącego się od wszystkiego, co serwer bazy danych obsługuje bezpośrednio, mogą korzystać z co najmniej jednej tabeli "LockedResources", aby śledzić, które zasoby powinny być zablokowane. Kod, który musi zdobyć zasób, zablokuje tabelę "LockedResources", zaktualizuje ją, aby pokazać, jakie zasoby należy zablokować, a następnie zwolnić; ta operacja na tabeli "LockedResource" będzie generalnie dość szybka (więc tabela "LockedResource" zostanie zablokowana tylko na krótko), nawet jeśli aplikacja musi utrzymywać rzeczywisty zasób przez długi czas. Jeśli jednak aplikacja ma wartość Environment.Exit, a tabela "LockedResources" wskazuje, że jest właścicielem zasobu, system operacyjny nie będzie miał pojęcia, jak zaktualizować tabelę "LockedResources", aby anulować taką własność.

Ogólnie, rzeczy takie jak aplikacje bazodanowe powinny być zaprojektowane tak, aby były niezawodne, nawet jeśli aplikacja klienta niespodziewanie umiera. Na przykład może istnieć tabela aktywnych klientów, przy czym każdy aktywny klient trzyma blokadę w rekordzie, który identyfikuje się. Jeśli klient, który chce użyć zasobu, zauważy, że tabela "LockedResources" wysłała go do innego klienta, były klient mógł sprawdzić, czy wpis ostatniego klienta w tabeli "aktywnych klientów" jest nadal zablokowany. Jeśli nie, może to oznaczać, że dany klient umarł i podjąć odpowiednie działania (uznając, że klient, który zmarł, mógł pozostawić swój zasób w złym stanie). Z drugiej strony fakt, że baza danych powinna być zaprojektowana tak, aby była niezawodna, jeśli klienci umierają niespodziewanie, nie oznacza, że ​​zawsze są. Zaniechanie zasobu nie jest dobrą rzeczą, nawet jeśli jest to możliwe do przeżycia .

Powiązane problemy