[ Pobierz całość w formacie PDF ]

tÄ™ instrukcjÄ™ try.
Jeśli wyjątek jest zgłaszany podczas wykonywania bloku finally i nie jest przechwytywany w ob-
rębie tego bloku, jest on propagowany do następnej obejmującej instrukcji try. Jeśli kolejny
wyjątek występuje w czasie propagacji, wyjątek ten zostaje utracony. Proces propagacji wyjątku
został dokładniej przedstawiony w opisie instrukcji throw (znajdującym się w punkcie 8.9.5).
BILL WAGNER Zachowanie to sprawia, że bardzo ważne jest pisanie klauzul finally
w sposób bezpieczny w celu uniknięcia ryzyka zgłoszenia drugiego wyjątku.
Blok try instrukcji try jest osiągalny, jeśli osiągalna jest ta instrukcja try.
Blok catch instrukcji try jest osiągalny, jeśli osiągalna jest ta instrukcja try.
Blok finally instrukcji try jest osiągalny, jeśli osiągalna jest ta instrukcja try.
Końcowy punkt instrukcji try jest osiągalny, jeśli spełnione są obydwa podane poniżej warunki:
" Osiągalny jest punkt końcowy bloku try lub osiągalny jest punkt końcowy przynajmniej
jednego bloku catch.
" Jeśli obecny jest blok finally, osiągalny jest punkt końcowy tego bloku finally.
8.11. Instrukcje checked i unchecked
Instrukcje checked i unchecked są używane do sterowania kontekstem kontroli przekroczenia
zakresu (ang. overflow checking context) w przypadku konwersji i operacji arytmetycznych na
typach całkowitych:
instrukcja-checked:
checked blok
instrukcja-unchecked:
unchecked blok
409
8. Instrukcje
Instrukcja checked powoduje, że wszystkie wyrażenia znajdujące się w elemencie blok są prze-
twarzane w kontekście kontrolowanym, zaś instrukcja unchecked powoduje, że wszystkie wyra-
żenia znajdujące się w elemencie blok są przetwarzane w kontekście niekontrolowanym.
Instrukcje checked i unchecked dokładnie odpowiadają operatorom checked i unchecked (opisanym
w punkcie 7.5.12), z wyjątkiem tego, że operują one na blokach wyrażeń.
8.12. Instrukcja lock
Instrukcja lock umożliwia nałożenie blokady wzajemnie wykluczającej na dany obiekt, wykonanie
instrukcji, a następnie zdjęcie tej blokady:
instrukcja-lock:
lock ( wyrażenie ) instrukcja-osadzona
Wyrażenie instrukcji lock musi oznaczać wartość typu, o którym wiadomo, że jest to typ-refe
rencyjny. Dla elementu wyrażenie instrukcji lock nigdy nie jest przeprowadzana niejawna
konwersja pakowania (o której więcej w punkcie 6.1.7). Z tego powodu pojawia się błąd czasu
kompilacji, jeśli wyrażenie oznacza wartość typ-wartościowy.
Instrukcja lock o postaci:
lock (x) ...
gdzie x jest wyrażeniem typ-referencyjny, jest dokładnie równoważna z kodem:
System.Threading.Monitor.Enter(x);
try {
...
}
finally {
System.Threading.Monitor.Exit(x);
}
z wyjątkiem tego, że x jest przetwarzane tylko raz.
ERIC LIPPERT Nieszczęśliwą konsekwencją wyboru tego sposobu generowania kodu
jest to, że w przypadku kompilacji przeznaczonych do debugowania pomiędzy operacją Enter
i blokiem try może występować  pusta instrukcja IL (te bezużyteczne w innych sytuacjach
instrukcje są często generowane po to, aby narzędzie diagnostyczne miało do dyspozycji
wyraznie określone miejsce, w którym można w razie potrzeby umieścić punkt przerwania
podczas procesu diagnozowania).
Jeśli uruchamiasz kompilację przeznaczoną do diagnozowania i nastąpi przełączenie wątku
podczas wykonywania tej operacji pustej, może się zdarzyć, że wyjątek przerwania wątku
zostaje zgłoszony w innym wątku. Przerwanie wątku może wystąpić przed wejściem do
410
8.12. Instrukcja lock
bloku try, dlatego blok finally nigdy nie jest wykonywany i blokada nigdy nie zostaje
zwolniona. Zachowanie takie może prowadzić do bardzo trudnych do zdiagnozowania sytu-
acji zakleszczenia.
Problem ten zostanie być może wyeliminowany w przyszłych wersjach C# za pomocą różnych
postaci operacji Enter, które będzie się dało bezpiecznie wywołać w ramach bloku try.
BILL WAGNER Użycie instrukcji lock() wiąże się również z dodatkowymi przeprowa-
dzanymi przez kompilator kontrolami tego, czy blokowanie nie dotyczy elementu typu warto-
ściowego.
Podczas utrzymywania blokady wzajemnie wykluczającej możliwe jest również nałożenie i zwol-
nienie blokady przez kod przetwarzany w ramach tego samego wątku wykonania. W przeciwień-
stwie do niego kod wykonywany w innych wątkach nie może nałożyć blokady, zanim bieżąca
blokada nie zostanie zwolniona.
Nie zaleca się blokowania obiektów System.Type w celu zsynchronizowania dostępu do danych
statycznych. Inny fragment kodu może zablokować ten sam typ, co może spowodować zakleszcze-
nie. Lepszym sposobem jest synchronizowanie dostępu do danych statycznych przez blokowanie
prywatnego obiektu statycznego. Przykład takiej operacji został przedstawiony poniżej:
class Cache
{
private static object synchronizationObject = new object();
public static void Add(object x) {
lock (Cache.synchronizationObject) {
...
}
}
public static void Remove(object x) {
lock (Cache.synchronizationObject) {
...
}
}
}
JOSEPH ALBAHARI DobrÄ… taktykÄ… przy pisaniu bibliotek przeznaczonych do publicz-
nego wykorzystania jest zabezpieczanie funkcji statycznych przed ubocznymi efektami dzia-
łania wielu różnych wątków (co można zwykle osiągnąć przez implementowanie blokady
w obrębie funkcji, tak jak zostało to przedstawione na powyższym przykładzie). Znacznie
trudniej jest użytkownikom kodu stosować blokadę wokół wywołania Twoich statycznych [ Pobierz całość w formacie PDF ]

  • zanotowane.pl
  • doc.pisz.pl
  • pdf.pisz.pl
  • centurion.xlx.pl