Dela via


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

Ger ett sätt att hantera vissa eller alla möjliga fel som kan uppstå i ett visst kodblock medan koden fortfarande körs.

Syntax

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

Delar

Period Definition
tryStatements Valfritt. Instruktioner där ett fel kan inträffa. Kan vara en sammansatt sats.
Catch Valfritt. Flera Catch block tillåts. Om ett undantag inträffar vid bearbetning av Try blocket granskas varje Catch -instruktion i textordning för att avgöra om undantaget hanteras, med exception ett undantag som representerar det undantag som har genererats.
exception Valfritt. Valfritt variabelnamn. Det initiala värdet exception för är värdet för det utlöses-felet. Används med Catch för att ange felet fångas. Om den utelämnas fångar instruktionen Catch upp alla undantag.
type Valfritt. Anger typ av klassfilter. Om värdet för exception är av den typ som anges av type eller av en härledd typ, blir identifieraren bunden till undantagsobjektet.
When Valfritt. En Catch instruktion med en When sats fångar endast undantag när expression utvärderas till True. En When sats tillämpas endast efter att ha kontrollerat typen av undantag och expression kan referera till identifieraren som representerar undantaget.
expression Valfritt. Måste implicit konverteras till Boolean. Alla uttryck som beskriver ett allmänt filter. Används vanligtvis för att filtrera efter felnummer. Används med When nyckelord för att ange omständigheter under vilka felet fångas.
catchStatements Valfritt. Instruktioner för att hantera fel som inträffar i det associerade Try blocket. Kan vara en sammansatt sats.
Exit Try Valfritt. Nyckelord som bryter ut ur Try...Catch...Finally strukturen. Körningen återupptas med koden omedelbart efter -instruktionen End Try . -instruktionen Finally kommer fortfarande att köras. Tillåts inte i Finally block.
Finally Valfritt. Ett Finally block körs alltid när körningen lämnar någon del av -instruktionen Try...Catch .
finallyStatements Valfritt. Instruktioner som körs efter att all annan felbearbetning har inträffat.
End Try Try...Catch...Finally Avslutar strukturen.

Kommentarer

Om du förväntar dig att ett visst undantag kan inträffa under ett visst kodavsnitt placerar du koden i ett Try block och använder ett Catch block för att behålla kontrollen och hantera undantaget om det inträffar.

En Try…Catch instruktion består av ett Try block följt av en eller flera Catch satser, som anger hanterare för olika undantag. När ett undantag utlöses i ett Try block letar Visual Basic efter instruktionen Catch som hanterar undantaget. Om en matchande Catch instruktion inte hittas undersöker Visual Basic metoden som anropade den aktuella metoden och så vidare upp anropsstacken. Om inget Catch block hittas visar Visual Basic ett ohanterat undantagsmeddelande till användaren och stoppar körningen av programmet.

Du kan använda mer än en Catch instruktion i en Try…Catch -instruktion. Om du gör detta är ordningen på klausulerna Catch betydande eftersom de granskas i ordning. Catch de mer specifika undantagen före de mindre specifika.

Följande Catch instruktionsvillkor är de minst specifika och kommer alla catch undantag som härleds från Exception klassen. Du bör vanligtvis använda en av dessa varianter som det sista Catch blocket i Try...Catch...Finally strukturen, efter att du har fångat alla specifika undantag som du förväntar dig. Kontrollflödet kan aldrig nå ett Catch block som följer någon av dessa varianter.

  • type är Exception, till exempel:Catch ex As Exception

  • -instruktionen har ingen exception variabel, till exempel: Catch

När en Try…Catch…Finally instruktion är kapslad i ett annat Try block undersöker Visual Basic först varje Catch instruktion i det innersta Try blocket. Om ingen matchande Catch instruktion hittas fortsätter sökningen till uttrycken Catch i det yttre Try…Catch…Finally blocket.

Lokala variabler från ett Try block är inte tillgängliga i ett Catch block eftersom de är separata block. Om du vill använda en variabel i mer än ett block deklarerar du variabeln utanför Try...Catch...Finally strukturen.

Dricks

-instruktionen Try…Catch…Finally är tillgänglig som ett IntelliSense-kodfragment. I Kodfragmenthanteraren expanderar du Kodmönster – Om, För varje,CatchTry , Egenskap osv. och sedan Felhantering (undantag). Mer information finns i Kodfragment.

Finally blockera

Om du har en eller flera instruktioner som måste köras innan du avslutar Try strukturen använder du ett Finally block. Kontrollen skickas Finally till blocket precis innan den skickas Try…Catch ut ur strukturen. Detta gäller även om ett undantag inträffar någonstans i Try strukturen.

Ett Finally block är användbart för att köra kod som måste köras även om det finns ett undantag. Kontrollen skickas till Finally blocket oavsett hur Try...Catch blocket avslutas.

Koden i ett Finally block körs även om koden påträffar en Return -instruktion i ett Try eller Catch ett block. Kontrollen skickas inte från ett Try eller Catch blockera till motsvarande Finally block i följande fall:

Det är inte giltigt att uttryckligen överföra körningen till ett Finally block. Överföring av körning från ett Finally block är inte giltigt, förutom genom ett undantag.

Om en Try instruktion inte innehåller minst ett Catch block måste den innehålla ett Finally block.

Dricks

Om du inte behöver catch specifika undantag fungerar -instruktionen Using som ett Try…Finally block och garanterar bortskaffande av resurserna, oavsett hur du avslutar blocket. Detta gäller även med ett ohanterat undantag. Mer information finns i Använda instruktion.

Undantagsargument

Blockargumentet Catch exception är en instans av Exception klassen eller en klass som härleds från Exception klassen. Klassinstansen Exception motsvarar felet som inträffade i Try blocket.

Egenskaperna för Exception objektet hjälper dig att identifiera orsaken till och platsen för ett undantag. Egenskapen listar till exempel StackTrace de metoder som ledde till undantaget, vilket hjälper dig att hitta var felet inträffade i koden. Message returnerar ett meddelande som beskriver undantaget. HelpLink returnerar en länk till en associerad hjälpfil. InnerException returnerar objektet Exception som orsakade det aktuella undantaget eller returnerar Nothing om det inte finns någon ursprunglig Exception.

Överväganden när du använder en Try…Catch instruktion

Använd endast en Try…Catch instruktion för att signalera förekomsten av ovanliga eller oväntade programhändelser. Orsaker till detta är bland annat följande:

  • Att fånga undantag vid körning skapar ytterligare omkostnader och kommer sannolikt att vara långsammare än förkontroll för att undvika undantag.

  • Om ett Catch block inte hanteras korrekt kanske undantaget inte rapporteras korrekt till användarna.

  • Undantagshantering gör ett program mer komplext.

Du behöver inte alltid en Try…Catch -instruktion för att söka efter ett villkor som sannolikt kommer att inträffa. I följande exempel kontrolleras om en fil finns innan du försöker öppna den. Detta minskar behovet av att fånga ett undantag som genereras av OpenText metoden.

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

Se till att kod i Catch block korrekt kan rapportera undantag till användare, oavsett om det gäller trådsäker loggning eller lämpliga meddelanden. Annars kan undantag förbli okända.

Asynkrona metoder

Om du markerar en metod med Async-modifieraren kan du använda Operatorn Await i -metoden. En instruktion med operatorn Await pausar körningen av metoden tills den väntande aktiviteten har slutförts. Uppgiften representerar pågående arbete. När aktiviteten som är associerad med operatorn Await är klar återupptas körningen med samma metod. Mer information finns i Kontrollera flöde i Async-program.

En uppgift som returneras av en Async-metod kan sluta i ett felaktigt tillstånd, vilket indikerar att den slutfördes på grund av ett ohanterat undantag. En uppgift kan också sluta i ett avbrutet tillstånd, vilket resulterar i att en OperationCanceledException utlöses från det väntande uttrycket. Om du vill catch använda någon av undantagstyperna placerar du uttrycket Await som är associerat med uppgiften i ett Try block och catch undantaget i blocket Catch . Ett exempel visas senare i det här avsnittet.

En uppgift kan vara i ett feltillstånd eftersom flera undantag var ansvariga för dess fel. Uppgiften kan till exempel vara resultatet av ett anrop till Task.WhenAll. När du väntar på en sådan uppgift är det fångade undantaget bara ett av undantagen och du kan inte förutsäga vilket undantag som ska fångas. Ett exempel visas senare i det här avsnittet.

Ett Await uttryck får inte finnas i ett Catch block eller Finally block.

Iteratorer

En iteratorfunktion eller Get -accessor utför en anpassad iteration över en samling. En iterator använder en Yield-instruktion för att returnera varje element i samlingen en i taget. Du anropar en iteratorfunktion med hjälp av en För varje... Nästa instruktion.

En Yield instruktion kan finnas i ett Try block. Ett Try block som innehåller en Yield -instruktion kan ha Catch block och kan ha ett Finally block. Ett exempel finns i Try Block.

En Yield instruktion får inte finnas i ett Catch block eller ett Finally block.

Om brödtexten For Each (utanför iteratorfunktionen) utlöser ett undantag körs inte ett Catch block i iteratorfunktionen, men ett Finally block i iteratorfunktionen körs. Ett Catch block i en iteratorfunktion fångar bara upp undantag som inträffar i iteratorfunktionen.

Situationer med partiellt förtroende

I situationer med partiellt förtroende, till exempel ett program som finns på en nätverksresurs, Try...Catch...Finally sker inte catch säkerhetsfel som inträffar innan metoden som innehåller anropet anropas. I följande exempel, när du placerar den på en serverresurs och kör därifrån, uppstår felet "System.Security.SecurityException: Begäran misslyckades". Mer information om säkerhetsfel finns i SecurityException klassen .

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

I en sådan partiell förtroendesituation måste du placera -instruktionen Process.Start i en separat Sub. Det första anropet Sub till kommer att misslyckas. Detta gör det möjligt Try...Catch innan catch som Sub innehåller startas Process.Start och säkerhetsfelet skapas.

Exempel

Strukturen för Try...Catch...Finally

I följande exempel visas instruktionens Try...Catch...Finally struktur.

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

Undantag i en metod som anropas från ett Try block

I följande exempel CreateException genererar metoden en NullReferenceException. Koden som genererar undantaget finns inte i ett Try block. CreateException Därför hanterar metoden inte undantaget. Metoden RunSample hanterar undantaget eftersom anropet CreateException till metoden är i ett Try block.

Exemplet innehåller Catch instruktioner för flera typer av undantag, ordnade från de mest specifika till de mest allmänna.

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

Instruktionen Catch När

I följande exempel visas hur du använder en Catch When -instruktion för att filtrera på ett villkorsuttryck. Om villkorsuttrycket utvärderas till Truekörs koden i Catch blocket.

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

Kapslade Try uttryck

I följande exempel finns en Try…Catch -instruktion som finns i ett Try block. Det inre Catch blocket genererar ett undantag som har dess InnerException egenskap inställd på det ursprungliga undantaget. Det yttre Catch blocket rapporterar sitt eget undantag och det inre undantaget.

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

Undantagshantering för asynkrona metoder

I följande exempel visas undantagshantering för asynkrona metoder. För catch ett undantag som gäller för en asynkron aktivitet Await finns uttrycket i ett Try block av anroparen och undantaget fångas i Catch blocket.

Ta bort kommentaren till Throw New Exception raden i exemplet för att demonstrera undantagshantering. Undantaget fångas i Catch blocket, aktivitetens IsFaulted egenskap är inställd på Trueoch aktivitetens Exception.InnerException egenskap är inställd på undantaget.

Ta bort kommentaren till Throw New OperationCancelledException raden för att visa vad som händer när du avbryter en asynkron process. Undantaget fångas i Catch blocket och aktivitetens IsCanceled egenskap är inställd på True. Men under vissa villkor som inte gäller för det här exemplet IsFaulted är inställt på True och IsCanceled är inställt på 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

Hantera flera undantag i asynkrona metoder

I följande exempel visas undantagshantering där flera uppgifter kan resultera i flera undantag. Blocket Try har uttrycket Await för den uppgift som Task.WhenAll returnerades. Uppgiften är slutförd när de tre aktiviteter som Task.WhenAll tillämpas är slutförda.

Var och en av de tre uppgifterna orsakar ett undantag. Blocket Catch itererar genom undantagen, som finns i Exception.InnerExceptions egenskapen för den uppgift som Task.WhenAll returnerades.

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

Se även