Try...Catch...Finally Anweisung (Visual Basic)
Stellt eine Möglichkeit zum Behandeln einiger oder aller Fehler dar, die in einem bestimmten Codeblock auftreten können, während der Code weiter ausgeführt wird.
Syntax
Try
[ tryStatements ]
[ Exit Try ]
[ Catch [ exception [ As type ] ] [ When expression ]
[ catchStatements ]
[ Exit Try ] ]
[ Catch ... ]
[ Finally
[ finallyStatements ] ]
End Try
Bestandteile
Begriff | Definition |
---|---|
tryStatements |
Dies ist optional. Anweisungen, in denen ein Fehler auftreten kann. Kann eine Verbundanweisung sein. |
Catch |
Optional. Mehrere Catch -Blöcke zulässig. Wenn beim Verarbeiten des Try -Blocks eine Ausnahme auftritt, wird jede Catch -Anweisung in textlicher Reihenfolge untersucht, um zu bestimmen, ob sie die Ausnahme behandelt, wobei exception sie die ausgelöste Ausnahme darstellt. |
exception |
Optional. Ein beliebiger Variablenname. Der Anfangswert von exception ist der Wert des ausgelösten Fehlers. Wird mit Catch verwendet, um den abgefangenen Fehler anzugeben. Wenn sie nicht angegeben wird, fängt die Catch -Anweisung eine Ausnahme ab. |
type |
Optional. Gibt den Typ des Filters an. Wenn der Wert von exception dem von type oder einem abgeleiteten Typ angegeben ist, wird der Bezeichner an das Ausnahmeobjekt gebunden. |
When |
Optional. Eine Catch -Anweisung mit einer When -Klausel fängt Ausnahmen nur ab, wenn expression sie mit True ausgewertet. Eine When -Klausel wird nur angewendet, nachdem der Typ der Ausnahme überprüft wurde, und expression kann auf den Bezeichner verweisen, der die Ausnahme darstellt. |
expression |
Optional. Muss implizit in Boolean konvertiert werden. Jeder Ausdruck, der einen generischen Filter beschreibt. Wird in der Regel verwendet, um nach Fehlernummer zu filtern. Wird mit When -Schlüsselwort (keyword) verwendet, um Umstände anzugeben, unter denen der Fehler abgefangen wird. |
catchStatements |
Optional. Anweisungen zur Behandlung von Fehlern, die im zugeordneten Try -Block auftreten. Kann eine Verbundanweisung sein. |
Exit Try |
Optional. Schlüsselwort, das aus der Try...Catch...Finally -Struktur herausbricht. Die Ausführung wird mit dem Code fortgesetzt, der unmittelbar auf die End Try -Anweisung folgt. Die Finally -Anweisung wird weiterhin ausgeführt. In Blöcken nicht zulässig Finally . |
Finally |
Optional. Ein Finally -Block wird immer ausgeführt, wenn die Ausführung einen Beliebigen Teil der Try...Catch -Anweisung verlässt. |
finallyStatements |
Optional. Anweisungen, die ohne Bedingung ausgeführt werden, nachdem die Behandlung sämtlicher Fehler abgeschlossen ist. |
End Try |
Beendet die Try...Catch...Finally Struktur. |
Bemerkungen
Wenn Sie erwarten, dass während eines bestimmten Codeabschnitts eine bestimmte Ausnahme auftreten kann, fügen Sie den Code in einen Try
-Block ein, und verwenden Sie einen Catch
-Block, um die Kontrolle beizubehalten und die Ausnahme zu behandeln, falls sie auftritt.
Die Try…Catch
-Anweisung besteht aus einem Try
-Block gefolgt von einer oder mehreren Catch
-Klauseln, die Handler für verschiedene Ausnahmen angeben. Wenn eine Ausnahme in einem Try
-Block ausgelöst wird, sucht Visual Basic nach der Catch
-Anweisung, die die Ausnahme behandelt. Wenn keine übereinstimmende Catch
-Anweisung gefunden wird, untersucht Visual Basic die Methode, die die aktuelle Methode aufgerufen hat, usw. im Aufrufstapel. Wenn kein Catch
-Block gefunden wird, zeigt Visual Basic dem Benutzer eine Meldung über eine nicht behandelte Ausnahme an und beendet die Ausführung des Programms.
Sie können mehr als eine Catch
-Anweisung in einer Try…Catch
-Anweisung verwenden. Wenn Sie dies tun, ist die Reihenfolge der Catch
-Klauseln von Bedeutung, da sie in der Reihenfolge untersucht werden. Catch Sie spezifischere Ausnahmen vor den weniger spezifischen ab.
Die folgenden Bedingungen der Catch
-Anweisung sind am wenigsten spezifisch und gelten für alle catch-Ausnahmen, die von der Exception-Klasse abgeleitet werden. Sie sollten normalerweise eine dieser Variationen als letzten Catch
-Block in der Try...Catch...Finally
-Struktur verwenden, nachdem Sie alle erwarteten spezifischen Ausnahmen abfangen. Der Ablauf der Steuerung kann nie einen Catch
-Block erreichen, der einer dieser Variationen folgt.
Der
type
istException
, z. B.:Catch ex As Exception
Die -Anweisung verfügt über keine
exception
-Variable, z. B.:Catch
Wenn eine Try…Catch…Finally
-Anweisung in einem anderen Try
-Block geschachtelt ist, untersucht Visual Basic zunächst jede Catch
-Anweisung im innersten Try
-Block. Wenn keine übereinstimmende Catch
-Anweisung gefunden wird, wird die Suche mit den Catch
-Anweisungen des äußeren Try…Catch…Finally
-Blocks fortgesetzt.
Lokale Variablen aus einem Try
-Block sind in einem Catch
-Block nicht verfügbar, da es sich um separate Blöcke handelt. Wenn Sie eine Variable in mehr als einem Block verwenden möchten, deklarieren Sie die Variable außerhalb der Try...Catch...Finally
-Struktur.
Tipp
Die Try…Catch…Finally
-Anweisung ist als IntelliSense-Codeausschnitt verfügbar. Erweitern Sie im Codeschnipsel-Manager Codemuster – If, For Each, TryCatch, Property usw. und dann Fehlerbehandlung (Ausnahmen). Weitere Informationen finden Sie unter Codeausschnitte.
Finally-Block
Wenn Sie über eine oder mehrere Anweisungen verfügen, die ausgeführt werden müssen, bevor Sie die Try
-Struktur beenden, verwenden Sie einen Finally
-Block. Das Steuerelement wird an den Finally
-Block übergeben, bevor er aus der Try…Catch
-Struktur ausgeht. Dies gilt auch dann, wenn an einer beliebigen Stelle innerhalb der Try
-Struktur eine Ausnahme auftritt.
Ein Finally
-Block ist nützlich, um Code auszuführen, der auch dann ausgeführt werden muss, wenn eine Ausnahme vorhanden ist. Das Steuerelement wird an den Finally
-Block übergeben, unabhängig davon, wie der Try...Catch
-Block beendet wird.
Der Code in einem Finally
-Block wird auch ausgeführt, wenn ihr Code auf eine Return
-Anweisung in einem Try
- oder Catch
-Block stößt. Das Steuerelement wird in den folgenden Fällen nicht von einem Try
- oder Catch
-Block an den entsprechenden Finally
-Block übergeben:
Im
Try
- oderCatch
-Block ist eine End-Anweisung vorhanden.Ein StackOverflowException wird im
Try
- oderCatch
-Block ausgelöst.
Es ist nicht gültig, die Ausführung explizit in einen Finally
-Block zu übertragen. Das Übertragen der Ausführung aus einem Finally
-Block ist außer über eine Ausnahme ungültig.
Wenn eine Try
-Anweisung nicht mindestens einen Catch
-Block enthält, muss sie einen Finally
-Block enthalten.
Tipp
Wenn für bestimmte Ausnahmen kein catch erforderlich ist, verhält sich die Using
-Anweisung wie ein Try…Finally
-Block und garantiert die Beseitigung der Ressourcen, unabhängig davon, wie Sie den Block beenden. Dies gilt auch bei einer unbehandelten Ausnahme. Weitere Informationen finden Sie unter using-Anweisung.
Ausnahmeargument
Das Catch
-Blockargument exception
ist eine Instanz der Exception-Klasse oder einer Klasse, die von der Exception
-Klasse abgeleitet ist. Die Exception
-Klasseninstanz entspricht dem Fehler, der im Try
-Block aufgetreten ist.
Die Eigenschaften des Exception
-Objekts helfen, die Ursache und den Speicherort einer Ausnahme zu identifizieren. Die StackTrace-Eigenschaft listet beispielsweise die aufgerufenen Methoden auf, die zu der Ausnahme geführt haben. So können Sie ermitteln, wo der Fehler im Code aufgetreten ist. Message ruft eine Meldung ab, in der die Ausnahme beschrieben wird. HelpLink gibt einen Link zu einer zugeordneten Hilfedatei zurück. InnerException gibt das Exception
-Objekt zurück, das die aktuelle Ausnahme verursacht hat, oder es wird zurückgegeben Nothing
, wenn kein originales Exception
vorhanden ist.
Überlegungen bei der Verwendung einer Try…Catch
-Anweisung
Verwenden Sie eine Try…Catch
-Anweisung nur, um das Auftreten ungewöhnlicher oder unerwarteter Programmereignisse zu signalisieren. Dies sind einige der Gründe für diese Vorgehensweise:
Das Abfangen von Ausnahmen zur Laufzeit verursacht zusätzlichen Mehraufwand und ist wahrscheinlich langsamer als die Vorabüberprüfung, um Ausnahmen zu vermeiden.
Wenn ein
Catch
-Block nicht ordnungsgemäß behandelt wird, wird die Ausnahme möglicherweise nicht ordnungsgemäß an Benutzer gemeldet.Die Ausnahmebehandlung macht ein Programm komplexer.
Sie benötigen nicht immer eine Try…Catch
-Anweisung, um nach einer Bedingung zu suchen, die wahrscheinlich auftreten wird. Im folgenden Beispiel wird überprüft, ob eine Datei vorhanden ist, bevor Sie versuchen, sie zu öffnen. Dies reduziert die Notwendigkeit, eine von der OpenText-Methode ausgelöste Ausnahme abzufangen.
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
Stellen Sie sicher, dass Code in Catch
-Blöcken Ausnahmen ordnungsgemäß an Benutzer melden kann, sei es durch threadsichere Protokollierung oder entsprechende Nachrichten. Andernfalls bleiben Ausnahmen möglicherweise unbekannt.
Asynchrone Methoden
Wenn Sie eine Methode mit dem Modifizierer async kennzeichnen, können Sie den Operator await in der Methode verwenden. Eine Anweisung mit dem Operator hält die Await
-Ausführung der Methode an, bis die erwartete Aufgabe abgeschlossen ist. Die Aufgabe stellt derzeit ausgeführte Arbeit dar. Wenn die dem Await
-Operator zugeordnete Aufgabe beendet wird, wird die Ausführung in derselben Methode fortgesetzt. Weitere Informationen finden Sie unter Ablaufsteuerung in asynchronen Programmen (C#).
Eine von einer Async-Methode zurückgegebene Aufgabe kann in einem fehlerhaften Zustand enden, der angibt, dass sie aufgrund einer nicht behandelten Ausnahme abgeschlossen wurde. Eine Aufgabe kann auch in einem abgebrochenen Zustand enden, was dazu führt, dass ein OperationCanceledException
aus dem await-Ausdruck geworfen wird. Für ein catch beider Ausnahmetypen, platzieren Sie den Await
-Ausdruck, der der Aufgabe zugeordnet ist, in einem Try
-Block, und führen Sie ein catch für die Ausnahme im Catch
-Block durch. Ein Beispiel finden Sie weiter unten in diesem Thema.
Eine Aufgabe kann sich in einem fehlerhaften Zustand befinden, da mehrere Ausnahmen für ihre Fehler verantwortlich waren. Beispielsweise kann die Aufgabe das Ergebnis eines Aufrufs an Task.WhenAll sein. Wenn Sie eine solche Aufgabe abwarten, ist die abgefangene Ausnahme nur eine der Ausnahmen, und Sie können nicht vorhersagen, welche Ausnahme abgefangen werden wird. Ein Beispiel finden Sie weiter unten in diesem Thema.
Ein Await
-Ausdruck darf sich nicht in einem Catch
-Block oder Finally
-Block befinden.
Iterators
Eine Iteratorfunktion oder eine Get
-Zugriffsmethode führt eine benutzerdefinierte Iteration einer Auflistung durch. Ein Iterator verwendet eine Yield-Anweisung, um jedes Element der Auflistung separat zurückzugeben. Sie rufen eine Iteratorfunktion mithilfe einer For Each…Next-Anweisung auf.
Eine Yield
-Anweisung kann sich innerhalb eines Try
-Blocks befinden. Ein Try
-Block mit einer Yield
-Anweisung kann über Catch
-Blöcke und über einen Finally
-Block verfügen. Ein Beispiel finden Sie unter Try-Blöcke.
Eine Yield
-Anweisung darf sich nicht in einem Catch
- oder Finally
-Block befinden.
Wenn der For Each
-Text (anstelle der Iteratorfunktion) eine Ausnahme auslöst, wird ein Catch
-Block in der Iteratorfunktion nicht ausgeführt, ein Finally
-Block in der Iteratorfunktion dagegen schon. Ein Catch
-Block in einer Iteratorfunktion fängt nur Ausnahmen ab, die innerhalb der Iteratorfunktion auftreten.
Teilweise vertrauenswürdige Situationen
In teilweise vertrauenswürdigen Situationen, z. B. einer Anwendung, die auf einer Netzwerkfreigabe gehostet wird, erfolgt mit Try...Catch...Finally
kein catch für Sicherheitsausnahmen, die auftreten, bevor die Methode aufgerufen wird, die den Aufruf enthält. Im folgenden Beispiel wird der Fehler "System.Security.SecurityException: Request Failed" (System.Security.SecurityException: Request Failed) angezeigt, wenn Sie es in einer Serverfreigabe platzieren und von dort ausführen. Weitere Informationen zu Sicherheitsausnahmen finden Sie in der SecurityException-Klasse.
Try
Process.Start("http://www.microsoft.com")
Catch ex As Exception
Console.WriteLine("Can't load Web page" & vbCrLf & ex.Message)
End Try
In einer solchen teilweise vertrauenswürdigen Situation müssen Sie die Process.Start
-Anweisung in eine separate Sub
einfügen. Beim ersten Aufruf von Sub
tritt ein Fehler auf. Dies ermöglicht Try...Catch
hierfür ein catch, bevor die Sub
, die Process.Start
enthält, gestartet und die Sicherheitsausnahme erzeugt wird.
Beispiele
Die Struktur von Try...Catch...Finally
Das folgende Beispiel veranschaulicht die Verwendung der Try...Catch...Finally
-Anweisung.
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
Ausnahme in einer Methode, die aus einem Try
-Block aufgerufen wird
Im folgenden Beispiel löst die CreateException
-Methode einen aus NullReferenceException
. Der Code, der die Ausnahme generiert, befindet sich nicht in einem Try
-Block. Daher verarbeitet die CreateException
-Methode die Ausnahme nicht. Die RunSample
-Methode verarbeitet die Ausnahme, da sich der Aufruf der CreateException
-Methode in einem Try
-Block befindet.
Das Beispiel enthält Catch
-Anweisungen für mehrere Arten von Ausnahmen, die von den spezifischsten bis zu den allgemeinsten sortiert sind.
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
Die Catch When-Anweisung
Das folgende Beispiel zeigt, wie Sie eine Catch When
-Anweisung verwenden, um nach einem bedingten Ausdruck zu filtern. Wenn der bedingte Ausdruck mit True
ausgewertet wird, wird der Code im Catch
Block ausgeführt.
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
Geschachtelte Try
-Anweisungen
Das folgende Beispiel enthält eine Try…Catch
-Anweisung, die in einem Try
-Block enthalten ist. Der innere Catch
-Block löst eine Ausnahme aus, deren InnerException
-Eigenschaft auf die ursprüngliche Ausnahme festgelegt ist. Der äußere Catch
-Block meldet eine eigene Ausnahme und die innere Ausnahme.
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
Ausnahmebehandlung für asynchrone Methoden
Im folgenden Beispiel wird die Ausnahmebehandlung für asynchrone Methoden veranschaulicht. Für den catch einer Ausnahme, die auf eine asynchrone Aufgabe angewendet wird, befindet sich der Await
-Ausdruck in einem Try
-Block des Aufrufers, und die Ausnahme wird im Catch
-Block abgefangen.
Heben Sie die Auskommentierung der Zeile Throw New Exception
im Beispiel auf, um die Ausnahmebehandlung zu veranschaulichen. Die Ausnahme wird im Catch
-Block abgefangen, die IsFaulted
-Eigenschaft der Aufgabe wird auf True
gesetzt und die Exception.InnerException
-Eigenschaft der Aufgabe wird auf die Ausnahme gesetzt.
Heben Sie die Auskommentierung der Zeile Throw New OperationCancelledException
auf, um zu veranschaulichen, was beim Abbrechen eines asynchronen Prozesses passiert. Die Ausnahme wird im Catch
-Block abgefangen, und die IsCanceled
-Eigenschaft der Aufgabe ist auf True
festgelegt. Unter bestimmten Bedingungen, die für dieses Beispiel nicht gelten, wird IsFaulted
auf True
und IsCanceled
auf False
festgelegt.
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
Behandeln mehrerer Ausnahmen in asynchronen Methoden
Das folgende Beispiel veranschaulicht die Behandlung von Ausnahmen in Fällen, in denen mehrere Aufgaben zu mehreren Ausnahmen führen können. Der Try
-Block verfügt über den Await
-Ausdruck für die Aufgabe, die Task.WhenAll zurückgibt. Die Aufgabe ist abgeschlossen, wenn die drei Aufgaben, auf die Task.WhenAll angewendet wird, abgeschlossen sind.
Jede der drei Aufgaben löst eine Ausnahme aus. Der Catch
-Block iteriert durch die Ausnahmen, die in der Exception.InnerExceptions
-Eigenschaft der Aufgabe stehen, die von Task.WhenAll
zurückgegeben wurde.
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