Po co używać try {} wreszcie {} z pustym blokiem try?


239

Zauważyłem, System.Threading.TimerBase.Dispose()że metoda ma try{} finally{}blok, ale try{}jest pusta.

Czy warto używać try{} finally{}pustego try?

http://labs.developerfusion.co.uk/SourceViewer/browse.aspx?assembly=SSCLI&namespace=System.Threading&type=TimerBase

[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
internal bool Dispose(WaitHandle notifyObject)
{
    bool status = false;
    bool bLockTaken = false;
    RuntimeHelpers.PrepareConstrainedRegions();
    try {
    }
    finally {
        do {
            if (Interlocked.CompareExchange(ref m_lock, 1, 0) == 0) {
                bLockTaken = true;
                try {
                    status = DeleteTimerNative(notifyObject.SafeWaitHandle);
                }
                finally {
                    m_lock = 0;
                }
            }
            Thread.SpinWait(1);
            // yield to processor
        }
        while (!bLockTaken);
        GC.SuppressFinalize(this);
    }

    return status;
}

System.Diagnostics.Process również wokół linii 2144: referenceource.microsoft.com/#System/services/monitoring/…
Patrick Artner,

Odpowiedzi:


171

From http://blog.somecreativity.com/2008/04/10/the-empty-try-block-mystery/ :

Ta metodologia chroni przed wywołaniem Thread.Abort przerywającym przetwarzanie. Strona MSDN Thread.Abort mówi, że „Ostatecznie niewykonane bloki są wykonywane przed przerwaniem wątku”. Aby więc zagwarantować, że przetwarzanie zakończy się, nawet jeśli Twój wątek zostanie przerwany w środku przez osobę wywołującą Przerwij w twoim wątku, możesz umieścić cały kod w ostatnim bloku (alternatywnie jest napisanie kodu w bloku „catch”, aby określ, gdzie byłeś, zanim „próbowanie” zostało przerwane przez Przerwij i kontynuuj stamtąd, jeśli chcesz).



15
Ponieważ nie było to możliwe, dopóki .NET 2.0
Hans Passant

6
@ RobFonseca-Ensor: Ponieważ Thread.BeginCriticalRegion()nie zapobiega to przerwaniu wątku, mówi raczej środowisku wykonawczemu, że jeśli wątek zostanie przerwany, to stan globalny jest uszkodzony, a cała domena może zabić litość.
kkm

9
@HansPassant: BeginCriticalSection()naprawdę nie było w NET 1.x, ale nie ma przyczyny i skutku, które implikują mówiąc dlatego . W rzeczywistości .NET 1.x nawet finallyblok mógł zostać przerwany przez przerwanie wątku. Mechanizmy te służą do innego celu: wykonywanie pracy w sposób finallyzapobiegający przerywaniu w połowie kodu, podczas gdy BeginCriticalSection()deklaruje tylko środowisku wykonawczemu, że stan globalny jest zagrożony.
kkm

Jeśli deweloper ma chwilę (prawda) w końcu, czy przerwanie kiedykolwiek się zakończy lub czy przerwanie technicznie może zostać zignorowane na czas nieokreślony?
Max Young

64

Ma to na celu ochronę przed Thread.Abortprzerwaniem procesu. Dokumentacja tej metody mówi, że:

Ostatecznie niewykonane bloki są wykonywane przed przerwaniem wątku.

Wynika to z faktu, że w celu pomyślnego odzyskania po błędzie kod będzie musiał wyczyścić się po sobie. Ponieważ C # nie ma niszczycieli w stylu C ++, finallya usingbloki są jedynym niezawodnym sposobem zapewnienia, że ​​takie czyszczenie jest przeprowadzane niezawodnie. Pamiętaj, że usingblok zmienia się w kompilator:

try {
    ...
}
finally {
    if(obj != null)
        ((IDisposable)obj).Dispose();
}

W .NET 1.x istniała szansa, że finallyblok zostanie przerwany. To zachowanie zostało zmienione w .NET 2.0.

Co więcej, puste trybloki nigdy nie są optymalizowane przez kompilator.


Dzięki za wgląd w blok używający.
Stefan,

@Anton Rozumiem, że używanie jest najlepszą praktyką. Ale do celów kpienia czasami trzeba zaimplementować klasę opakowania, a obiekt jednorazowy staje się zmienną klasy prywatnej. Jeśli sprawimy, że to opakowanie będzie jednorazowe, to czy GC nie będzie automatycznie zajmować się usuwaniem zmiennej klasy prywatnej?
Ozkan

@Ozkan GC nie usuwa niczego automatycznie. Musisz zaimplementować finalizator, zwykle wywołując Dispose(false);. docs.microsoft.com/en-us/dotnet/standard/garbage-collection/...
Thorarin

@Thorarin przepraszam, ale mylisz się, mówiąc, że GC nie pozbywa się (finalizuje) automatycznie.
Ozkan
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.