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 True wartość . 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 wszystkie catch 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
toException
, 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 Try
Finally
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:
Element StackOverflowException jest zgłaszany w
Try
bloku lubCatch
.
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 wykonywać catch 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:
Przechwytywanie wyjątków w czasie wykonywania powoduje dodatkowe obciążenie i prawdopodobnie będzie 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. W catch przypadku dowolnego typu wyjątku umieść Await
wyrażenie skojarzone z zadaniem w Try
bloku i catch 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 catch powoduje 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 Sub
pliku . Początkowe wywołanie metody zakończy się niepowodzeniem Sub
. Umożliwia Try...Catch
catch to jego uruchomienie przed uruchomieniem Sub
tego pliku Process.Start
i utworzonym wyjątkiem 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 NullReferenceException
błą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 True
zwró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. W catch przypadku wyjątku, 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 IsFaulted
Exception.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 True
wartość . 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 False
wartość .
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