Megosztás a következőn keresztül:


Try...Catch...Finally Utasítás (Visual Basic)

Lehetővé teszi egy adott kódblokkban esetlegesen előforduló hibák vagy hibák kezelését, miközben továbbra is futtatja a kódot.

Syntax

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

Részek

Időszak Definíció
tryStatements Opcionális. Utasítás(ok), ahol hiba léphet fel. Összetett utasítás is lehet.
Catch Opcionális. Több Catch blokk engedélyezett. Ha a blokk feldolgozása során kivétel történik, az Try egyes Catch állításokat szöveges sorrendben vizsgáljuk meg annak megállapításához, hogy az kezeli-e a kivételt, a kidobott kivételt jelölve exception .
exception Opcionális. Bármely változó neve. A kezdeti érték exception a kidobott hiba értéke. Catch A kifogott hiba megadására szolgál. Ha nincs megadva, az Catch utasítás kivételt észlel.
type Opcionális. Megadja az osztályszűrő típusát. Ha az érték exception egy származtatott típus által type megadott vagy származtatott típus, akkor az azonosító a kivételobjektumhoz lesz kötve.
When Opcionális. A Catch záradékkal rendelkező When utasítások csak akkor kapnak kivételt, ha expression a kiértékelés eredménye.True A When záradék csak a kivétel típusának ellenőrzése után lesz alkalmazva, és expression hivatkozhat a kivételt jelképező azonosítóra.
expression Opcionális. Implicit módon konvertálhatónak Booleankell lennie . Minden olyan kifejezés, amely általános szűrőt ír le. Általában hibaszám alapján történő szűrésre használják. Kulcsszóval When adhatja meg a hibát észlelő körülményeket.
catchStatements Opcionális. Utasítás(ok) a társított Try blokkban előforduló hibák kezelésére. Összetett utasítás is lehet.
Exit Try Opcionális. A szerkezetből Try...Catch...Finally kitörő kulcsszó. A végrehajtás az utasítást közvetlenül követő End Try kóddal folytatódik. Az Finally utasítás továbbra is végrehajtásra kerül. Blokkokban Finally nem engedélyezett.
Finally Opcionális. A Finally blokkok mindig akkor lesznek végrehajtva, ha a Try...Catch végrehajtás az utasítás bármely részét elhagyja.
finallyStatements Opcionális. Az összes többi hibafeldolgozás után végrehajtott utasítás(ok).
End Try Leállítja a struktúrát Try...Catch...Finally .

Megjegyzések

Ha arra számít, hogy egy adott kivétel a kód egy adott szakaszában fordulhat elő, helyezze a kódot egy Try blokkba, és használjon blokkot Catch a vezérlő megtartásához és a kivétel kezeléséhez, ha az előfordul.

Az Try…Catch utasítás egy Try blokkból és egy vagy több Catch záradékból áll, amelyek különböző kivételek kezelőit határozzák meg. Ha kivételt ad egy Try blokkba, a Visual Basic megkeresi a Catch kivételt kezelő utasítást. Ha nem található egyező Catch utasítás, a Visual Basic megvizsgálja az aktuális metódusnak nevezett metódust, és így tovább a hívási vermet. Ha nem Catch található blokk, a Visual Basic nem kezelt kivételüzenetet jelenít meg a felhasználónak, és leállítja a program végrehajtását.

Egy utasításban Catch több utasítást Try…Catch is használhat. Ha ezt teszi, a záradékok sorrendje Catch jelentős, mert a záradékok sorrendben vannak megvizsgálva. Catch a kevésbé specifikus kivételek előtt.

Az alábbi Catch utasításfeltételek a legkevésbé specifikusak, és az osztályból Exception származó összes kivételt elkapják. Általában ezen változatok egyikét kell használnia a struktúra utolsó Catch blokkjaként Try...Catch...Finally , miután elfogta az összes várt kivételt. A vezérlési folyamat soha nem érhet el olyan blokkot Catch , amely bármelyik változatot követi.

  • Ez type például a következő Exception: Catch ex As Exception

  • Az utasítás nem exception rendelkezik változóval, például: Catch

Ha egy utasítás egy Try…Catch…Finally másik Try blokkba van ágyazva, a Visual Basic először megvizsgálja a legbelső blokk összes Catch utasítását Try . Ha nem található egyező Catch utasítás, a keresés a Catch külső Try…Catch…Finally blokk utasításaira folytatódik.

A Try blokkok helyi változói nem érhetők el blokkokban Catch , mert különálló blokkok. Ha több blokkban szeretne változót használni, deklarálja a változót a Try...Catch...Finally struktúrán kívül.

Tipp.

Az Try…Catch…Finally utasítás IntelliSense kódrészletként érhető el. A Kódrészletek kezelőjében bontsa ki a Kódminták – Ha, Mindegyik, TryCatchTulajdonság stb. elemet, majd a Hibakezelés (Kivételek) elemet. További információ: Kódrészletek.

Finally blokk

Ha egy vagy több utasítást kell futtatnia, mielőtt kilép a Try struktúrából, használjon blokkot Finally . A vezérlő átmegy a Finally blokkra, mielőtt kimegy a Try…Catch szerkezetből. Ez akkor is igaz, ha a struktúra bármely pontján Try kivétel történik.

A Finally blokkok akkor is hasznosak, ha olyan kódot futtatnak, amelyet kivétel esetén is végre kell hajtani. A vezérlőt a rendszer a Finally blokk kilépési módjától függetlenül továbbítja a Try...Catch blokknak.

A blokkokban lévő Finally kód akkor is fut, ha a kód egy vagy Catch több Return blokkban lévő utasítást Try talál. A vezérlő nem halad át egy Try vagy Catch több blokkból a megfelelő Finally blokkba a következő esetekben:

Nem érvényes a végrehajtás explicit átadása blokkba Finally . A végrehajtás blokkból való átvitele Finally nem érvényes, kivéve egy kivételt.

Ha egy Try utasítás nem tartalmaz legalább egy Catch blokkot, annak blokkot Finally kell tartalmaznia.

Tipp.

Ha nem kell bizonyos kivételeket elkapnia, az Using utasítás blokkként Try…Finally viselkedik, és garantálja az erőforrások ártalmatlanítását, függetlenül attól, hogy hogyan lép ki a blokkból. Ez még kezeletlen kivétel esetén is igaz. További információ: Az utasítás használata.

Kivétel argumentuma

A Catch blokkargumentum exception az Exception osztály egy példánya, vagy egy osztály, amely az Exception osztályból származik. Az Exception osztálypéldány a blokkban Try előforduló hibának felel meg.

Az objektum tulajdonságai Exception segítenek azonosítani a kivétel okát és helyét. A tulajdonság például felsorolja azokat StackTrace az úgynevezett metódusokat, amelyek a kivételhez vezettek, és segítenek megtalálni, hogy hol történt a hiba a kódban. Message A kivételt leíró üzenetet ad vissza. HelpLink egy társított súgófájlra mutató hivatkozást ad vissza. InnerExceptionException Az aktuális kivételt okozó objektumot adja visszaNothing, vagy ha nincs eredetiException.

Megfontolandó szempontok utasítás Try…Catch használatakor

Csak utasítással Try…Catch jelezheti a szokatlan vagy nem várt programesemények előfordulását. Ennek okai a következők:

  • Catcha kivételek futásidőben történő használata további többletterhelést okoz, és valószínűleg lassabb, mint az előzetes ellenőrzés a kivételek elkerülése érdekében.

  • Ha egy Catch blokk kezelése nem megfelelően történik, előfordulhat, hogy a kivételt nem megfelelően jelenti a rendszer a felhasználóknak.

  • A kivételkezelés összetettebbé teszi a programot.

Nem mindig van szüksége Try…Catch utasításra egy valószínűleg előforduló feltétel ellenőrzéséhez. Az alábbi példa ellenőrzi, hogy létezik-e fájl a megnyitás előtt. Ez csökkenti a metódus által OpenText kidobott kivételek elfogásának szükségességét.

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

Győződjön meg arról, hogy a blokkokban lévő Catch kód képes megfelelően jelenteni a felhasználók kivételeit, akár szálbiztos naplózással, akár megfelelő üzenetekkel. Ellenkező esetben előfordulhat, hogy a kivételek ismeretlenek maradnak.

Aszinkron metódusok

Ha az Async módosítóval jelöl meg egy metódust, használhatja a Metódus Várakozás operátorát. Az operátorral rendelkező Await utasítás felfüggeszti a metódus végrehajtását, amíg a várt tevékenység be nem fejeződik. A tevékenység a folyamatban lévő munkát jelöli. Amikor az operátorhoz Await társított feladat befejeződik, a végrehajtás ugyanabban a metódusban folytatódik. További információ: Control Flow in Async Programs.

Az Async-metódus által visszaadott feladat hibás állapotban végződhet, ami azt jelzi, hogy kezeletlen kivétel miatt fejeződött be. A tevékenységek megszakított állapotban is végződhetnek, ami azt eredményezi OperationCanceledException , hogy a várt kifejezés ki lesz dobva. A kivétel bármelyik típusának elfogásához helyezze a Await tevékenységhez társított kifejezést egy Try blokkba, és a kivételt a blokkban Catch . A témakör későbbi részében egy példa látható.

A tevékenységek hibás állapotban lehetnek, mert több kivétel is felelős a hibákért. Előfordulhat például, hogy a feladat egy hívás Task.WhenAlleredménye. Ha egy ilyen feladatra vár, a kifogott kivétel csak az egyik kivétel, és nem tudja előre megjósolni, hogy melyik kivétel fog kifogni. A témakör későbbi részében egy példa látható.

A Await kifejezések nem lehetnek blokkban vagy Finally blokkbanCatch.

Iterátorok

Egy iterátorfüggvény vagy Get tartozék egyéni iterációt hajt végre egy gyűjteményen keresztül. Az iterátor egy Hozam utasítással egyenként adja vissza a gyűjtemény minden elemét. Iterátorfüggvényt hívhat meg minden egyeshöz... Következő utasítás.

Az Yield utasítás egy blokkon belül Try is lehet. Az Try utasítást Yield tartalmazó blokkok blokkokat tartalmazhatnak Catch , és blokkokkal Finally is rendelkezhetnek. Példa: Try Blokkok.

Az Yield utasítás nem lehet blokkban Catch vagy blokkban Finally .

Ha a For Each törzs (az iterátorfüggvényen kívül) kivételt jelez, Catch az iterátorfüggvény blokkja nem lesz végrehajtva, de az iterátorfüggvény egy Finally blokkja lesz végrehajtva. Az Catch iterátorfüggvényen belüli blokkok csak az iterátorfüggvényben előforduló kivételeket rögzítik.

Részleges megbízhatósági helyzetek

Részleges megbízhatósági helyzetekben, például egy hálózati megosztáson üzemeltetett alkalmazás, Try...Catch...Finally nem észleli a hívást tartalmazó metódus meghívása előtt előforduló biztonsági kivételeket. Az alábbi példa, amikor egy kiszolgálómegosztásra helyezi, és onnan futtatja, a következő hibát eredményezi: "System.Security.SecurityException: Request Failed". A biztonsági kivételekkel kapcsolatos további információkért tekintse meg az osztályt SecurityException .

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

Ilyen részleges megbízhatósági helyzetben a nyilatkozatot külön Subkell elhelyeznie Process.Start . A kezdeti hívás Sub sikertelen lesz. Ez lehetővé teszi Try...Catch , hogy elfogja azt, mielőtt a Sub benne lévő Process.Start fájl elindul, és a biztonsági kivétel létrejön.

Példák

A Try...Catch...Finally

Az alábbi példa az utasítás szerkezetét Try...Catch...Finally mutatja be.

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

Kivétel blokkból Try hívott metódusban

Az alábbi példában a CreateException metódus egy NullReferenceException. A kivételt létrehozó kód nincs blokkban Try . Ezért a CreateException metódus nem kezeli a kivételt. A RunSample metódus kezeli a kivételt, mert a CreateException metódus hívása blokkban Try van.

A példa számos kivételtípusra vonatkozó utasításokat tartalmaz Catch , amelyek a legkiváltabbtól a legátlagosabbaktól lesznek rendezve.

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

A Catch Mikor utasítás

Az alábbi példa bemutatja, hogyan használható utasítás egy Catch When feltételes kifejezésre való szűréshez. Ha a feltételes kifejezés kiértékelése folyamatban Truevan, a blokkban lévő Catch kód lefut.

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

Try Beágyazott utasítások

Az alábbi példa egy Try…Catch blokkban található utasítással Try rendelkezik. A belső Catch blokk kivételt hoz létre, amelynek tulajdonsága InnerException az eredeti kivételre van állítva. A külső Catch blokk a saját kivételét és a belső kivételt jelenti.

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

Az aszinkron metódusok kivételkezelése

Az alábbi példa az aszinkron metódusok kivételkezelését mutatja be. Ha egy aszinkron tevékenységre vonatkozó kivételt szeretne elkapni, a Await kifejezés a hívó blokkjában Try van, és a kivétel a Catch blokkban van.

Bontsa ki a Throw New Exception példában szereplő sort a kivételkezelés bemutatásához. A kivétel a Catch blokkban van, a tevékenység tulajdonsága IsFaulted a kivételre van állítva True, a tevékenység tulajdonsága Exception.InnerException pedig a kivételre van állítva.

Bontsa ki a sort, Throw New OperationCancelledException hogy bemuhassa, mi történik az aszinkron folyamat megszakításakor. A kivétel a Catch blokkban van, és a tevékenység tulajdonsága IsCanceled a következőre Truevan állítva: . Bizonyos feltételek mellett azonban, amelyek nem vonatkoznak erre a példára, IsFaulted a beállítás True értéke a IsCanceledFalsekövetkező.

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

Több kivétel kezelése az aszinkron metódusokban

Az alábbi példa a kivételkezelést mutatja be, ahol több tevékenység több kivételt eredményezhet. A Try blokk a Await visszaadott feladat Task.WhenAll kifejezésével rendelkezik. A tevékenység akkor fejeződik be, ha az alkalmazott három tevékenység Task.WhenAll befejeződött.

A három tevékenység mindegyike kivételt okoz. A Catch blokk végigvezeti a kivételeket, amelyek a Exception.InnerExceptions visszaadott feladat Task.WhenAll tulajdonságában találhatók.

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

Lásd még