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

Zapewnia sposób obsługi niektórych lub wszystkich możliwych błędów, które mogą wystąpić w danym bloku kodu, jednocześnie uruchamiając kod.

Składnia

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

generatora

Termin Definicja
tryStatements Opcjonalny. Instrukcje, w których może wystąpić błąd. Może być instrukcją złożoną.
Catch Opcjonalny. Dozwolone jest wiele Catch bloków. Jeśli wystąpi wyjątek podczas przetwarzania Try bloku, każda Catch instrukcja jest badana w kolejności tekstowej, aby określić, czy obsługuje wyjątek, z reprezentowaniem exception wyjątku, który został zgłoszony.
exception Opcjonalny. Dowolna nazwa zmiennej. Początkowa wartość to wartość exception zgłaszanego błędu. Catch Służy do określania błędu przechwyconego. W przypadku pominięcia instrukcja Catch przechwytuje wszelkie wyjątki.
type Opcjonalny. Określa typ filtru klasy. Jeśli wartość exception jest typu określonego przez type lub typu pochodnego, identyfikator staje się powiązany z obiektem wyjątku.
When Opcjonalny. Instrukcja Catch z klauzulą When przechwytuje wyjątki tylko wtedy, gdy expression wartość jest obliczana na Truewartość . Klauzula When jest stosowana tylko po sprawdzeniu typu wyjątku i expression może odwoływać się do identyfikatora reprezentującego wyjątek.
expression Opcjonalny. Musi być niejawnie konwertowany na Boolean. Dowolne wyrażenie, które opisuje filtr ogólny. Zazwyczaj służy do filtrowania według numeru błędu. When Słowo kluczowe służy do określania okoliczności, w których błąd jest przechwycony.
catchStatements Opcjonalny. Instrukcje do obsługi błędów występujących w skojarzonym Try bloku. Może być instrukcją złożoną.
Exit Try Opcjonalny. Słowo kluczowe, które wyrywa się ze Try...Catch...Finally struktury. Wykonanie jest wznawiane przy użyciu kodu bezpośrednio po instrukcji End Try . Instrukcja Finally będzie nadal wykonywana. Niedozwolone w Finally blokach.
Finally Opcjonalny. Blok Finally jest zawsze wykonywany, gdy wykonanie pozostawia dowolną część instrukcji Try...Catch .
finallyStatements Opcjonalny. Instrukcje, które są wykonywane po każdym innym przetwarzaniu błędów.
End Try Try...Catch...Finally Przerywa strukturę.

Uwagi

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

Instrukcja Try…Catch składa się z Try bloku, po którym następuje co najmniej jedna Catch klauzula, która określa procedury obsługi dla różnych wyjątków. Po wystąpieniu wyjątku w bloku program Visual Basic szuka Catch instrukcji obsługującej Try wyjątek. Jeśli nie można odnaleźć zgodnej Catch instrukcji, Visual Basic sprawdza metodę, która nazywa się bieżącą metodą, i tak dalej na stosie wywołań. Jeśli żaden blok nie Catch zostanie znaleziony, program Visual Basic wyświetli użytkownikowi komunikat o nieobsługiwanym wyjątku i zatrzyma wykonywanie programu.

W instrukcji można użyć więcej niż jednej Catch instrukcji Try…Catch . W takim przypadku kolejność Catch klauzul jest znacząca, ponieważ są one badane w kolejności. Catch bardziej szczegółowe wyjątki przed mniej konkretnymi wyjątkami.

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

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

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

Try…Catch…Finally Gdy instrukcja jest zagnieżdżona w innym Try bloku, program Visual Basic najpierw sprawdza każdą Catch instrukcję w najbardziej Try wewnętrznym bloku. Jeśli nie zostanie znaleziona żadna zgodna Catch instrukcja, wyszukiwanie przejdzie do Catch instrukcji bloku zewnętrznego Try…Catch…Finally .

Zmienne lokalne z Try bloku 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 strukturą Try...Catch...Finally .

Napiwek

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

Blok Finally

Jeśli masz co najmniej jedną instrukcję, która musi zostać uruchomiona przed zamknięciem TryFinally struktury, użyj bloku. Kontrolka Finally przechodzi do bloku tuż przed wyjściem Try…Catch ze struktury. Jest to prawdą, nawet jeśli 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 istnieje wyjątek. Kontrolka jest przekazywana Finally do bloku niezależnie od sposobu zamykania Try...Catch bloku.

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

  • W bloku lub Catch napotkano instrukcję Try End.

  • Element StackOverflowException jest zgłaszany w Try bloku lub Catch .

Jawne przeniesienie wykonania do Finally bloku jest nieprawidłowe. Przenoszenie wykonania z Finally bloku jest nieprawidłowe, z wyjątkiem wyjątku.

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

Napiwek

Jeśli nie musisz przechwytywać określonych wyjątków, Using instrukcja zachowuje się jak Try…Finally blok i gwarantuje usunięcie zasobów, niezależnie od sposobu zamknięcia bloku. Dotyczy to nawet nieobsługiwanego wyjątku. Aby uzyskać więcej informacji, zobacz Using Statement (Używanie instrukcji).

Argument wyjątku

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

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

Zagadnienia dotyczące korzystania z instrukcji Try…Catch

Try…Catch Użyj instrukcji tylko do sygnalizatora wystąpienia nietypowych lub nieprzewidzianych zdarzeń programu. Przyczyny tego problemu obejmują następujące kwestie:

  • CatchWyjątki w czasie wykonywania tworzą dodatkowe nakłady pracy i prawdopodobnie będą wolniejsze niż wstępne sprawdzanie, aby uniknąć wyjątków.

  • Catch Jeśli blok nie jest poprawnie obsługiwany, wyjątek może nie zostać poprawnie zgłoszony użytkownikom.

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

Nie zawsze potrzebujesz Try…Catch instrukcji , aby sprawdzić stan, który prawdopodobnie wystąpi. Poniższy przykład sprawdza, czy plik istnieje przed próbą jego otwarcia. Zmniejsza to potrzebę przechwycenia wyjątku zgłaszanego przez metodę OpenText .

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 Catch blokach może prawidłowo zgłaszać wyjątki dla użytkowników, niezależnie od tego, czy jest to rejestrowanie bezpieczne wątkowo, czy odpowiednie komunikaty. W przeciwnym razie wyjątki mogą pozostać nieznane.

Metody asynchroniczne

Jeśli oznaczysz metodę za pomocą modyfikatora asynchronicznego , możesz użyć operatora Await w metodzie . Instrukcja z operatorem Await zawiesza wykonywanie metody do momentu zakończenia oczekiwanego zadania. Zadanie reprezentuje bieżącą pracę. Po zakończeniu zadania skojarzonego z operatorem Await wykonywanie zostanie wznowione w tej samej metodzie. Aby uzyskać więcej informacji, zobacz Przepływ sterowania w programach asynchronicznych.

Zadanie zwrócone przez metodę Async może kończyć się błędnym stanem wskazującym, że zostało ukończone z powodu nieobsługiwanego wyjątku. Zadanie może również kończyć się stanem anulowanym, co skutkuje wyrzuceniem OperationCanceledException z wyrażenia await. Aby przechwycić dowolny typ wyjątku, umieść Await wyrażenie skojarzone z zadaniem w Try bloku i przechwyć wyjątek w Catch bloku. W dalszej części tego tematu podano przykład.

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 metody Task.WhenAll. W przypadku oczekiwania na takie zadanie wyjątek przechwycony jest tylko jednym z wyjątków i nie można przewidzieć, który wyjątek zostanie przechwycony. W dalszej części tego tematu podano przykład.

Wyrażenie Await nie może znajdować się wewnątrz Catch bloku lub Finally bloku.

Iteratory

Funkcja iteratora lub Get akcesoryja wykonuje niestandardową iterację w kolekcji. Iterator używa instrukcji Yield , aby zwrócić każdy element kolekcji pojedynczo. Funkcja iteratora jest wywoływana przy użyciu funkcji Dla każdego... Następna instrukcja.

Instrukcja Yield może znajdować się wewnątrz Try bloku. Blok Try zawierający instrukcję Yield może zawierać Catch bloki i może mieć Finally blok. Aby zapoznać się z przykładem, zobacz Try Bloki.

Instrukcja Yield nie może znajdować się wewnątrz Catch bloku lub Finally bloku.

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

Sytuacje dotyczące częściowego zaufania

W sytuacjach częściowych zaufania, takich jak aplikacja hostowana w udziale sieciowym, Try...Catch...Finally nie przechwytuje wyjątków zabezpieczeń występujących przed wywołaniem metody zawierającej wywołanie. Poniższy przykład, gdy umieścisz go w udziale serwera i uruchomisz z tego miejsca, powoduje błąd "System.Security.SecurityException: Żądanie nie powiodło się". Aby uzyskać więcej informacji na temat wyjątków zabezpieczeń, zobacz klasę SecurityException .

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

W takiej sytuacji z częściowym zaufaniem należy umieścić instrukcję Process.Start w osobnym Subpliku . Początkowe wywołanie metody zakończy się niepowodzeniem Sub . Dzięki temu można Try...Catch go przechwycić przed uruchomieniem Sub , Process.Start a wygenerowany wyjątek zabezpieczeń.

Przykłady

Struktura Try...Catch...Finally

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

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.
        Console.WriteLine("end of Try block")
    Catch ex As Exception
        ' Show the exception's message.
        Console.WriteLine(ex.Message)

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

Wyjątek w metodzie wywoływanej Try z bloku

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

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

Public Sub RunSample()
    Try
        CreateException()
    Catch ex As System.IO.IOException
        ' Code that reacts to IOException.
    Catch ex As NullReferenceException
        Console.WriteLine("NullReferenceException: " & ex.Message)
        Console.WriteLine("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 używać Catch When instrukcji do filtrowania w wyrażeniu warunkowym. Jeśli wyrażenie warunkowe Truezwróci wartość , kod w Catch bloku zostanie uruchomiony.

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

Instrukcje zagnieżdżone Try

Poniższy przykład zawiera instrukcję Try…Catch zawartą Try w 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 dotyczy zadania asynchronicznego, Await wyrażenie znajduje się w Try bloku obiektu wywołującego, a wyjątek jest przechwycony w Catch bloku.

Usuń komentarz z Throw New Exception wiersza w przykładzie, aby zademonstrować obsługę wyjątków. Wyjątek jest przechwytywane w Catch bloku, właściwość zadania jest ustawiona na True, a właściwość zadania IsFaultedException.InnerException jest ustawiona na wyjątek.

Usuń komentarz z wiersza, Throw New OperationCancelledException aby zademonstrować, co się stanie po anulowaniu procesu asynchronicznego. Wyjątek jest przechwycony w Catch bloku, a właściwość zadania jest ustawiona IsCanceled na Truewartość . Jednak w niektórych warunkach, które nie mają zastosowania do tego przykładu, IsFaulted jest ustawiona na True wartość i IsCanceled jest ustawiona na Falsewartość .

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 których wiele zadań może spowodować wiele wyjątków. Blok Try zawiera Await wyrażenie dla zwróconego zadania Task.WhenAll . Zadanie jest wykonywane po zakończeniu trzech zadań, do których Task.WhenAll zastosowano.

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 zadania Task.WhenAll .

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ż