Try...Catch...Finally Statement (Visual Basic)
Provides a way to handle some or all possible errors that may occur in a given block of code, while still running code.
Try [ tryStatements ] [ Exit Try ] [ Catch [ exception [ As type ] ] [ When expression ] [ catchStatements ] [ Exit Try ] ] [ Catch ... ] [ Finally [ finallyStatements ] ] End Try
||Optional. Statement(s) where an error can occur. Can be a compound statement.|
||Optional. Any variable name. The initial value of
||Optional. Specifies the type of class filter. If the value of
||Optional. Must be implicitly convertible to
||Optional. Statement(s) to handle errors that occur in the associated
||Optional. Keyword that breaks out of the
||Optional. Statement(s) that are executed after all other error processing has occurred.|
If you expect that a particular exception might occur during a particular section of code, put the code in a
Try block and use a
Catch block to retain control and handle the exception if it occurs.
Try…Catch statement consists of a
Try block followed by one or more
Catch clauses, which specify handlers for various exceptions. When an exception is thrown in a
Try block, Visual Basic looks for the
Catch statement that handles the exception. If a matching
Catch statement is not found, Visual Basic examines the method that called the current method, and so on up the call stack. If no
Catch block is found, Visual Basic displays an unhandled exception message to the user and stops execution of the program.
You can use more than one
Catch statement in a
Try…Catch statement. If you do this, the order of the
Catch clauses is significant because they are examined in order. Catch the more specific exceptions before the less specific ones.
Catch statement conditions are the least specific, and will catch all exceptions that derive from the Exception class. You should ordinarily use one of these variations as the last
Catch block in the
Try...Catch...Finally structure, after catching all the specific exceptions you expect. Control flow can never reach a
Catch block that follows either of these variations.
Exception, for example:
Catch ex As Exception
The statement has no
exceptionvariable, for example:
Try…Catch…Finally statement is nested in another
Try block, Visual Basic first examines each
Catch statement in the innermost
Try block. If no matching
Catch statement is found, the search proceeds to the
Catch statements of the outer
Local variables from a
Try block are not available in a
Catch block because they are separate blocks. If you want to use a variable in more than one block, declare the variable outside the
Try…Catch…Finally statement is available as an IntelliSense code snippet. In the Code Snippets Manager, expand Code Patterns - If, For Each, Try Catch, Property, etc, and then Error Handling (Exceptions). For more information, see Code Snippets.
If you have one or more statements that must run before you exit the
Try structure, use a
Finally block. Control passes to the
Finally block just before it passes out of the
Try…Catch structure. This is true even if an exception occurs anywhere inside the
Finally block is useful for running any code that must execute even if there is an exception. Control is passed to the
Finally block regardless of how the
Try...Catch block exits.
The code in a
Finally block runs even if your code encounters a
Return statement in a
Catch block. Control does not pass from a
Catch block to the corresponding
Finally block in the following cases:
An End Statement is encountered in the
A StackOverflowException is thrown in the
It is not valid to explicitly transfer execution into a
Finally block. Transferring execution out of a
Finally block is not valid, except through an exception.
Try statement does not contain at least one
Catch block, it must contain a
If you do not have to catch specific exceptions, the
Using statement behaves like a
Try…Finally block, and guarantees disposal of the resources, regardless of how you exit the block. This is true even with an unhandled exception. For more information, see Using Statement.
exception argument is an instance of the Exception class or a class that derives from the
Exception class. The
Exception class instance corresponds to the error that occurred in the
The properties of the
Exception object help to identify the cause and location of an exception. For example, the StackTrace property lists the called methods that led to the exception, helping you find where the error occurred in the code. Message returns a message that describes the exception. HelpLink returns a link to an associated Help file. InnerException returns the
Exception object that caused the current exception, or it returns
Nothing if there is no original
Considerations When Using a Try…Catch Statement
Try…Catch statement only to signal the occurrence of unusual or unanticipated program events. Reasons for this include the following:
Catching exceptions at runtime creates additional overhead, and is likely to be slower than pre-checking to avoid exceptions.
Catchblock is not handled correctly, the exception might not be reported correctly to users.
Exception handling makes a program more complex.
You do not always need a
Try…Catch statement to check for a condition that is likely to occur. The following example checks whether a file exists before trying to open it. This reduces the need for catching an exception thrown by the OpenText method.
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
Ensure that code in
Catch blocks can properly report exceptions to users, whether through thread-safe logging or appropriate messages. Otherwise, exceptions might remain unknown.
If you mark a method with the Async modifier, you can use the Await operator in the method. A statement with the
Await operator suspends execution of the method until the awaited task completes. The task represents ongoing work. When the task that's associated with the
Await operator finishes, execution resumes in the same method. For more information, see Control Flow in Async Programs.
A task returned by an Async method may end in a faulted state, indicating that it completed due to an unhandled exception. A task may also end in a canceled state, which results in an
OperationCanceledException being thrown out of the await expression. To catch either type of exception, place the
Await expression that's associated with the task in a
Try block, and catch the exception in the
Catch block. An example is provided later in this topic.
A task can be in a faulted state because multiple exceptions were responsible for its faulting. For example, the task might be the result of a call to Task.WhenAll. When you await such a task, the caught exception is only one of the exceptions, and you can't predict which exception will be caught. An example is provided later in this topic.
Await expression can't be inside a
Catch block or
An iterator function or
Get accessor performs a custom iteration over a collection. An iterator uses a Yield statement to return each element of the collection one at a time. You call an iterator function by using a For Each...Next Statement.
Yield statement can be inside a
Try block. A
Try block that contains a
Yield statement can have
Catch blocks, and can have a
Finally block. See the "Try Blocks in Visual Basic" section of Iterators for an example.
Yield statement cannot be inside a
Catch block or a
For Each body (outside of the iterator function) throws an exception, a
Catch block in the iterator function is not executed, but a
Finally block in the iterator function is executed. A
Catch block inside an iterator function catches only exceptions that occur inside the iterator function.
In partial-trust situations, such as an application hosted on a network share,
Try...Catch...Finally does not catch security exceptions that occur before the method that contains the call is invoked. The following example, when you put it on a server share and run from there, produces the error "System.Security.SecurityException: Request Failed." For more information about security exceptions, see the SecurityException class.
Try Process.Start("http://www.microsoft.com") Catch ex As Exception MsgBox("Can't load Web page" & vbCrLf & ex.Message) End Try
In such a partial-trust situation, you have to put the
Process.Start statement in a separate
Sub. The initial call to the
Sub will fail. This enables
Try...Catch to catch it before the
Sub that contains
Process.Start is started and the security exception produced.
The following example illustrates the structure of the
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
In the following example, the
CreateException method throws a
NullReferenceException. The code that generates the exception is not in a
Try block. Therefore, the
CreateException method does not handle the exception. The
RunSample method does handle the exception because the call to the
CreateException method is in a
The example includes
Catch statements for several types of exceptions, ordered from the most specific to the most general.
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
The following example shows how to use a
Catch When statement to filter on a conditional expression. If the conditional expression evaluates to
True, the code in the
Catch block runs.
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
The following example has a
Try…Catch statement that is contained in a
Try block. The inner
Catch block throws an exception that has its
InnerException property set to the original exception. The outer
Catch block reports its own exception and the inner exception.
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
The following example illustrates exception handling for async methods. To catch an exception that applies to an async task, the
Await expression is in a
Try block of the caller, and the exception is caught in the
Throw New Exception line in the example to demonstrate exception handling. The exception is caught in the
Catch block, the task's
IsFaulted property is set to
True, and the task's
Exception.InnerException property is set to the exception.
Throw New OperationCancelledException line to demonstrate what happens when you cancel an asynchronous process. The exception is caught in the
Catch block, and the task's
IsCanceled property is set to
True. However, under some conditions that don't apply to this example,
IsFaulted is set to
IsCanceled is set to
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
The following example illustrates exception handling where multiple tasks can result in multiple exceptions. The
Try block has the
Await expression for the task that Task.WhenAll returned. The task is complete when the three tasks to which Task.WhenAll is applied are complete.
Each of the three tasks causes an exception. The
Catch block iterates through the exceptions, which are found in the
Exception.InnerExceptions property of the task that
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