Try...Catch...Finally — Instrukcja (Visual Basic)

Umożliwia obsługę niektórych lub wszystkich możliwych błędów, które mogą wystąpić w danym bloku kodu, podczas gdy kod jest nadal uruchomiony.

Składnia

Try
    [ tryStatements ]
    [ Exit Try ]
[ Catch [ exception [ As type ] ] [ When expression ]
    [ catchStatements ]
    [ Exit Try ] ]
[ Catch ... ]
[ Finally
    [ finallyStatements ] ]
End Try

Części

Okres Definicja
tryStatements Opcjonalny. Instrukcje, w których może wystąpić błąd. Może to być instrukcja złożona.
Catch Opcjonalny. Dozwolonych Catch jest wiele bloków. Jeśli podczas przetwarzania bloku wystąpi wyjątek, każda instrukcja jest analizowana w kolejności tekstowej, aby określić, czy obsługuje wyjątek, z reprezentacją zgłoszonego Try Catch exception wyjątku.
exception Opcjonalny. Dowolna nazwa zmiennej. Wartość początkowa exception jest wartością zgłoszonego błędu. Służy do Catch określania przechwyconego błędu. W przypadku pominięcia instrukcja Catch przechwytuje wszelkie wyjątki.
type Opcjonalny. Określa typ filtru klasy. Jeśli wartość jest typu określonego przez lub typu pochodnego, identyfikator jest powiązany exception type z obiektem wyjątku.
When Opcjonalny. Instrukcja Catch z klauzulą When przechwytuje wyjątki tylko wtedy, expression gdy ma wartość True . Klauzula jest stosowana tylko po sprawdzeniu typu wyjątku i może odwoływać się do When expression identyfikatora reprezentującego wyjątek.
expression Opcjonalny. Musi być niejawnie konwertowalny na Boolean . Dowolne wyrażenie opisujące filtr ogólny. Zwykle używany do filtrowania według numeru błędu. Używane ze When słowem kluczowym , aby określić okoliczności, w których zostanie przechwycony błąd.
catchStatements Opcjonalny. Instrukcje do obsługi błędów, które występują w skojarzonym Try bloku. Może to być instrukcja złożona.
Exit Try Opcjonalny. Słowo kluczowe, które wyłamuje się ze Try...Catch...Finally struktury. Wykonywanie jest wznawiane przy użyciu kodu bezpośrednio po End Try instrukcji . Instrukcja Finally będzie nadal wykonywana. Niedozwolone w Finally blokach.
Finally Opcjonalny. Blok Finally jest zawsze wykonywany, gdy wykonanie pozostawia dowolną część Try...Catch instrukcji.
finallyStatements Opcjonalny. Instrukcje, które są wykonywane po zakończeniu wszystkich innych przetwarzania błędów.
End Try Kończy Try...Catch...Finally strukturę.

Uwagi

Jeśli oczekujesz, że określony wyjątek może wystąpić w określonej sekcji kodu, umieść kod w bloku i użyj bloku, aby zachować kontrolę i obsługiwać wyjątek, jeśli Try Catch wystąpi.

Instrukcja składa się z bloku, po którym następuje co najmniej jedna Try…Catch Try Catch klauzula określająca procedury obsługi dla różnych wyjątków. Gdy w bloku zostanie zgłoszony wyjątek, Visual Basic Try szuka Catch instrukcji, która obsługuje wyjątek. Jeśli nie znaleziono pasującej instrukcji, Visual Basic metoda, która wywołała bieżącą metodę, i tak Catch dalej stos wywołań. Jeśli blok nie zostanie znaleziony, Visual Basic komunikat o nieobsługiwanym wyjątku dla użytkownika Catch i zatrzyma wykonywanie programu.

W instrukcji można użyć więcej niż Catch jednej Try…Catch instrukcji . Jeśli to zrobisz, kolejność klauzul jest istotna, ponieważ Catch są one analizowane w kolejności. Przechwyć bardziej szczegółowe wyjątki przed mniej specyficznymi wyjątkami.

Poniższe warunki Catch instrukcji są najmniej specyficzne i przechwytują wszystkie wyjątki pochodzące z klasy Exception . Zwykle należy używać jednej z tych odmian jako ostatniego bloku w strukturze po przechwyceniu wszystkich Catch Try...Catch...Finally określonych wyjątków, których oczekujesz. Przepływ sterowania nigdy nie może osiągnąć Catch bloku, który jest zgodny z jedną z tych odmian.

  • Jest type Exception , na przykład: Catch ex As Exception

  • Instrukcja nie ma exception zmiennej, na przykład: Catch

Gdy instrukcja Try…Catch…Finally jest zagnieżdżona w innym bloku, Visual Basic najpierw sprawdza każdą instrukcje Try w najbardziej wewnętrznym Catch Try bloku. Jeśli nie znaleziono pasującej instrukcji, wyszukiwanie przechodzi do instrukcji Catch Catch bloku Try…Catch…Finally zewnętrznego.

Zmienne lokalne z bloku Try nie są dostępne w Catch bloku, ponieważ są oddzielnymi blokami. Jeśli chcesz użyć zmiennej w więcej niż jednym bloku, zadeklaruj zmienną poza Try...Catch...Finally strukturą.

Porada

Instrukcja Try…Catch…Finally jest dostępna jako fragment kodu funkcji IntelliSense. W Menedżerze fragmentów kodu rozwiń pozycję Wzorce kodu — Jeśli, Dla każdego, Wypróbuj catch, właściwość itp., a następnie pozycję Obsługa błędów (wyjątki). Aby uzyskać więcej informacji, zobacz Fragmenty kodu.

Na koniec blokuj

Jeśli masz co najmniej jedną instrukcje, które muszą zostać uruchomione przed wyjściem ze Try struktury, użyj Finally bloku. Kontrolka przechodzi do Finally bloku tuż przed upływem Try…Catch struktury. Dzieje się tak nawet wtedy, gdy wyjątek występuje w dowolnym miejscu wewnątrz Try struktury.

Blok Finally jest przydatny do uruchamiania dowolnego kodu, który musi zostać wykonany, nawet jeśli występuje wyjątek. Kontrolka jest przekazywana Finally do bloku niezależnie od sposobu zakończenia Try...Catch bloku.

Kod w bloku jest uruchamiany nawet wtedy, gdy Finally kod napotka instrukcje w bloku Return lub Try Catch . Kontrolka nie przechodzi z Try bloku lub Catch do odpowiedniego bloku w następujących Finally przypadkach:

Jawne przeniesienie wykonywania do bloku jest Finally nieprawidłowe. Transferowanie wykonywania poza Finally blok nie jest prawidłowe, z wyjątkiem wyjątku.

Jeśli instrukcja Try nie zawiera co najmniej jednego Catch bloku, musi zawierać Finally blok.

Porada

Jeśli nie trzeba przechwytować określonych wyjątków, instrukcja zachowuje się jak blok i gwarantuje usunięcie zasobów, niezależnie od sposobu wyjścia Using Try…Finally z bloku. Jest to prawdziwe nawet w przypadku nieobsługiwanego wyjątku. Aby uzyskać więcej informacji, zobacz Using, instrukcja.

Argument wyjątku

Argument Catch bloku jest wystąpieniem klasy lub klasy, exception która pochodzi od klasy Exception Exception . Wystąpienie Exception klasy odpowiada błędowi, który wystąpił w Try bloku.

Właściwości obiektu Exception pomagają zidentyfikować przyczynę i lokalizację wyjątku. Na przykład właściwość wyświetla listę wywołanych metod, które doprowadziły do wyjątku, pomagając w odnalezieniu miejsca wystąpienia StackTrace błędu w kodzie. Message Zwraca komunikat opisujący wyjątek. HelpLink zwraca link do skojarzonego pliku pomocy. InnerException Zwraca Exception obiekt, który spowodował bieżący wyjątek, lub zwraca wartość , Nothing jeśli nie ma oryginalnego obiektu Exception .

Zagadnienia dotyczące korzystania z narzędzia Try... Catch, instrukcja

Instrukcja umożliwia tylko sygnalizowanie wystąpienia nietypowych lub Try…Catch nieprzewidzianych zdarzeń programu. Przyczyny tego są następujące:

  • Przechwytowanie wyjątków w czasie wykonywania powoduje dodatkowe obciążenie i prawdopodobnie będzie wolniejsze niż wstępne sprawdzanie w celu uniknięcia wyjątków.

  • Jeśli blok Catch nie jest obsługiwany prawidłowo, wyjątek może nie być prawidłowo zgłaszany użytkownikom.

  • Obsługa wyjątków sprawia, że program jest bardziej złożony.

Nie zawsze jest potrzebna Try…Catch instrukcja , aby sprawdzić stan, który może wystąpić. Poniższy przykład sprawdza, czy plik istnieje, zanim spróbuje go otworzyć. Zmniejsza to potrzebę przechwytowania wyjątku zgłoszonego przez OpenText metodę .

Private Sub TextFileExample(ByVal filePath As String)

    ' Verify that the file exists.
    If System.IO.File.Exists(filePath) = False Then
        Console.Write("File Not Found: " & filePath)
    Else
        ' Open the text file and display its contents.
        Dim sr As System.IO.StreamReader =
            System.IO.File.OpenText(filePath)

        Console.Write(sr.ReadToEnd)

        sr.Close()
    End If
End Sub

Upewnij się, że kod w blokach może prawidłowo zgłaszać wyjątki użytkownikom za pośrednictwem bezpiecznego Catch wątkowo rejestrowania lub odpowiednich komunikatów. W przeciwnym razie wyjątki mogą pozostać nieznane.

Metody asynchroniczne

Jeśli oznaczysz metodę za pomocą modyfikatora Async, możesz użyć operatora Await w metodzie . Instrukcja z Await operatorem wstrzymuje wykonywanie metody do momentu zakończenia oczekującego zadania. Zadanie reprezentuje bieżącą pracę. Po zakończeniu zadania skojarzonego z Await operatorem wykonywanie zostanie wznowione w tej samej metodzie. Aby uzyskać więcej informacji, zobacz Control Flow in Async Programs.

Zadanie zwrócone przez metodę Async może zakończyć się stanem błędu wskazującym, że zostało ono ukończone z powodu nieobsługiwanego wyjątku. Zadanie może również zakończyć się stanem anulowania, co powoduje wyrzucanie OperationCanceledException z wyrażenia await. Aby przechwyć jeden z typów wyjątków, umieść wyrażenie skojarzone z zadaniem w bloku i przechwyć Await Try wyjątek w Catch bloku. Przykład znajduje się w dalszej części tego tematu.

Zadanie może być w stanie błędu, ponieważ wiele wyjątków było odpowiedzialnych za jego błędy. Na przykład zadanie może być wynikiem wywołania do Task.WhenAll . Gdy oczekujesz na takie zadanie, przechwycony wyjątek jest tylko jednym z wyjątków i nie można przewidzieć, który wyjątek zostanie przechwycony. Przykład znajduje się w dalszej części tego tematu.

Wyrażenie Await nie może być wewnątrz bloku ani Catch Finally bloku.

Iteratory

Funkcja iteratora lub Get accessor wykonuje niestandardową iterację na kolekcji. Iterator używa instrukcji Yield, aby zwracać po jednym elemencie kolekcji po jednym na raz. Aby wywołać funkcję iteratora, należy użyć funkcji For Each... Następna instrukcja.

Instrukcja Yield może być wewnątrz Try bloku. Blok Try zawierający Yield instrukcje może mieć bloki i Catch Finally blok. Zobacz sekcję "Wypróbuj bloki w Visual Basic" iteratorów, aby uzyskać przykład.

Instrukcja Yield nie może być wewnątrz bloku ani Catch Finally bloku.

Jeśli treść (poza funkcją iteratora) zgłasza wyjątek, blok w funkcji iteratora nie jest wykonywany, ale jest wykonywany blok w funkcji For Each Catch Finally iteratora. Blok Catch wewnątrz funkcji iteratora przechwytuje tylko wyjątki występujące wewnątrz funkcji iteratora.

Sytuacje z częściowym zaufaniem

W sytuacjach częściowego zaufania, takich jak aplikacja hostowana w udziału sieciowym, nie przechwytuje wyjątków zabezpieczeń, które występują przed wywołaniem metody zawierającej Try...Catch...Finally wywołanie. W poniższym przykładzie po wrzuceniu go do udziału serwera i uruchomieniu z niego powoduje błąd "System.Security.SecurityException: Request Failed" (System.Security.SecurityException: Żądanie nie powiodło się). Aby uzyskać więcej informacji na temat wyjątków zabezpieczeń, zobacz SecurityException klasę .

Try
    Process.Start("http://www.microsoft.com")
Catch ex As Exception
    MsgBox("Can't load Web page" & vbCrLf & ex.Message)
End Try

W takiej sytuacji częściowego zaufania należy umieścić instrukcji Process.Start w osobnym Sub . Początkowe wywołanie do wywołania Sub nie powiedzie się. Dzięki temu Try...Catch można go przechwytować przed Sub rozpoczęciem zawiera i Process.Start wyjątku zabezpieczeń.

Przykłady

Struktura try... Złapać... Wreszcie

Poniższy przykład ilustruje strukturę Try...Catch...Finally instrukcji .

Public Sub TryExample()
    ' Declare variables.
    Dim x As Integer = 5
    Dim y As Integer = 0

    ' Set up structured error handling.
    Try
        ' Cause a "Divide by Zero" exception.
        x = x \ y

        ' This statement does not execute because program
        ' control passes to the Catch block when the
        ' exception occurs.
        MessageBox.Show("end of Try block")
    Catch ex As Exception
        ' Show the exception's message.
        MessageBox.Show(ex.Message)

        ' Show the stack trace, which is a list of methods
        ' that are currently executing.
        MessageBox.Show("Stack Trace: " & vbCrLf & ex.StackTrace)
    Finally
        ' This line executes whether or not the exception occurs.
        MessageBox.Show("in Finally block")
    End Try
End Sub

Wyjątek w metodzie o nazwie z bloku Try

W poniższym przykładzie CreateException metoda zgłasza wyjątek NullReferenceException . Kod, który generuje wyjątek, nie znajduje się w Try bloku. W związku z CreateException tym metoda nie obsługuje wyjątku. Metoda RunSample obsługuje wyjątek, ponieważ wywołanie metody znajduje się w CreateException Try bloku.

Przykład zawiera instrukcje dla kilku typów wyjątków uporządkowane od najbardziej specyficznych Catch do najbardziej ogólnych.

Public Sub RunSample()
    Try
        CreateException()
    Catch ex As System.IO.IOException
        ' Code that reacts to IOException.
    Catch ex As NullReferenceException
        MessageBox.Show("NullReferenceException: " & ex.Message)
        MessageBox.Show("Stack Trace: " & vbCrLf & ex.StackTrace)
    Catch ex As Exception
        ' Code that reacts to any other exception.
    End Try
End Sub

Private Sub CreateException()
    ' This code throws a NullReferenceException.
    Dim obj = Nothing
    Dim prop = obj.Name

    ' This code also throws a NullReferenceException.
    'Throw New NullReferenceException("Something happened.")
End Sub

Instrukcja Catch When

W poniższym przykładzie pokazano, jak za pomocą Catch When instrukcji filtrować według wyrażenia warunkowego. Jeśli wyrażenie warunkowe ma wartość True , zostanie uruchomiony kod w Catch bloku.

Private Sub WhenExample()
    Dim i As Integer = 5

    Try
        Throw New ArgumentException()
    Catch e As OverflowException When i = 5
        Console.WriteLine("First handler")
    Catch e As ArgumentException When i = 4
        Console.WriteLine("Second handler")
    Catch When i = 5
        Console.WriteLine("Third handler")
    End Try
End Sub
' Output: Third handler

Zagnieżdżone instrukcje Try

Poniższy przykład zawiera Try…Catch instrukcje zawarte w Try bloku. Blok wewnętrzny Catch zgłasza wyjątek, który ma właściwość InnerException ustawioną na oryginalny wyjątek. Blok zewnętrzny Catch zgłasza własny wyjątek i wyjątek wewnętrzny.

Private Sub InnerExceptionExample()
    Try
        Try
            ' Set a reference to a StringBuilder.
            ' The exception below does not occur if the commented
            ' out statement is used instead.
            Dim sb As System.Text.StringBuilder
            'Dim sb As New System.Text.StringBuilder

            ' Cause a NullReferenceException.
            sb.Append("text")
        Catch ex As Exception
            ' Throw a new exception that has the inner exception
            ' set to the original exception.
            Throw New ApplicationException("Something happened :(", ex)
        End Try
    Catch ex2 As Exception
        ' Show the exception.
        Console.WriteLine("Exception: " & ex2.Message)
        Console.WriteLine(ex2.StackTrace)

        ' Show the inner exception, if one is present.
        If ex2.InnerException IsNot Nothing Then
            Console.WriteLine("Inner Exception: " & ex2.InnerException.Message)
            Console.WriteLine(ex2.StackTrace)
        End If
    End Try
End Sub

Obsługa wyjątków dla metod asynchronicznych

Poniższy przykład ilustruje obsługę wyjątków dla metod asynchronicznych. Aby przechwycić wyjątek, który ma zastosowanie do zadania asynchronicznego, wyrażenie znajduje się w bloku wywołującego, a wyjątek jest przechwycony Await Try w Catch bloku.

Odkomentuj Throw New Exception wiersz w przykładzie, aby zademonstrować obsługę wyjątków. Wyjątek jest przechwycony w bloku, właściwość zadania jest ustawiona na , a właściwość zadania jest Catch IsFaulted True Exception.InnerException ustawiona na wyjątek.

Odkomentuj Throw New OperationCancelledException wiersz, aby zademonstrować, co się dzieje po anulowaniu procesu asynchronicznego. Wyjątek jest przechwycony w bloku, a właściwość zadania jest Catch IsCanceled ustawiona na True wartość . Jednak w pewnych warunkach, które nie mają zastosowania do tego przykładu, wartość jest ustawiona na IsFaulted i True jest IsCanceled ustawiona na False .

Public Async Function DoSomethingAsync() As Task
    Dim theTask As Task(Of String) = DelayAsync()

    Try
        Dim result As String = Await theTask
        Debug.WriteLine("Result: " & result)
    Catch ex As Exception
        Debug.WriteLine("Exception Message: " & ex.Message)
    End Try

    Debug.WriteLine("Task IsCanceled: " & theTask.IsCanceled)
    Debug.WriteLine("Task IsFaulted:  " & theTask.IsFaulted)
    If theTask.Exception IsNot Nothing Then
        Debug.WriteLine("Task Exception Message: " &
            theTask.Exception.Message)
        Debug.WriteLine("Task Inner Exception Message: " &
            theTask.Exception.InnerException.Message)
    End If
End Function

Private Async Function DelayAsync() As Task(Of String)
    Await Task.Delay(100)

    ' Uncomment each of the following lines to
    ' demonstrate exception handling.

    'Throw New OperationCanceledException("canceled")
    'Throw New Exception("Something happened.")
    Return "Done"
End Function


' Output when no exception is thrown in the awaited method:
'   Result: Done
'   Task IsCanceled: False
'   Task IsFaulted:  False

' Output when an Exception is thrown in the awaited method:
'   Exception Message: Something happened.
'   Task IsCanceled: False
'   Task IsFaulted:  True
'   Task Exception Message: One or more errors occurred.
'   Task Inner Exception Message: Something happened.

' Output when an OperationCanceledException or TaskCanceledException
' is thrown in the awaited method:
'   Exception Message: canceled
'   Task IsCanceled: True
'   Task IsFaulted:  False

Obsługa wielu wyjątków w metodach asynchronicznych

Poniższy przykład ilustruje obsługę wyjątków, w przypadku której wiele zadań może powodować wiele wyjątków. Blok Try zawiera Await wyrażenie dla zwróconego Task.WhenAll zadania. Zadanie jest wykonywane po zakończeniu trzech zadań, do Task.WhenAll których zastosowano te trzy zadania.

Każde z trzech zadań powoduje wyjątek. Blok Catch iteruje przez wyjątki, które znajdują się we Exception.InnerExceptions właściwości zwróconego Task.WhenAll zadania.

Public Async Function DoMultipleAsync() As Task
    Dim theTask1 As Task = ExcAsync(info:="First Task")
    Dim theTask2 As Task = ExcAsync(info:="Second Task")
    Dim theTask3 As Task = ExcAsync(info:="Third Task")

    Dim allTasks As Task = Task.WhenAll(theTask1, theTask2, theTask3)

    Try
        Await allTasks
    Catch ex As Exception
        Debug.WriteLine("Exception: " & ex.Message)
        Debug.WriteLine("Task IsFaulted: " & allTasks.IsFaulted)
        For Each inEx In allTasks.Exception.InnerExceptions
            Debug.WriteLine("Task Inner Exception: " + inEx.Message)
        Next
    End Try
End Function

Private Async Function ExcAsync(info As String) As Task
    Await Task.Delay(100)

    Throw New Exception("Error-" & info)
End Function

' Output:
'   Exception: Error-First Task
'   Task IsFaulted: True
'   Task Inner Exception: Error-First Task
'   Task Inner Exception: Error-Second Task
'   Task Inner Exception: Error-Third Task

Zobacz też