Try...Catch...Finally Příkaz (Visual Basic)
Poskytuje způsob, jak zpracovat některé nebo všechny možné chyby, ke kterým může docházet v daném bloku kódu, zatímco stále běží kód.
Syntaxe
Try
[ tryStatements ]
[ Exit Try ]
[ Catch [ exception [ As type ] ] [ When expression ]
[ catchStatements ]
[ Exit Try ] ]
[ Catch ... ]
[ Finally
[ finallyStatements ] ]
End Try
Součástky
Pojem | definice |
---|---|
tryStatements |
Nepovinné. Příkazy, u kterých může dojít k chybě. Může to být složený příkaz. |
Catch |
Nepovinné. Je povoleno více Catch bloků. Pokud při zpracování Try bloku dojde k výjimce, je každý Catch příkaz zkoumán v textovém pořadí, aby zjistil, zda zpracovává výjimku, a exception představuje výjimku, která byla vyvolána. |
exception |
Nepovinné. Libovolný název proměnné. Počáteční hodnota je hodnota exception vyvolané chyby. Catch Používá se k určení zachycené chyby. Pokud tento parametr vynecháte, Catch zachytí všechny výjimky. |
type |
Nepovinné. Určuje typ filtru třídy. Pokud je hodnota exception typu určeného typem type nebo odvozeným typem, identifikátor se stane vázán na objekt výjimky. |
When |
Nepovinné. Příkaz Catch s When klauzulí zachytává výjimky pouze v případech, kdy expression se vyhodnotí jako True . When Klauzule se použije pouze po kontrole typu výjimky a expression může odkazovat na identifikátor představující výjimku. |
expression |
Nepovinné. Musí být implicitně konvertibilní na Boolean . Libovolný výraz, který popisuje obecný filtr. Obvykle se používá k filtrování podle čísla chyby. Používá se s klíčovým slovem When k určení okolností, za kterých se chyba zachytila. |
catchStatements |
Nepovinné. Příkazy pro zpracování chyb, ke kterým dochází v přidruženém Try bloku. Může to být složený příkaz. |
Exit Try |
Nepovinné. Klíčové slovo, které rozdělí Try...Catch...Finally strukturu. Provádění se obnoví kódem bezprostředně za příkazem End Try . Příkaz Finally bude stále proveden. Nepovoleno v Finally blocích. |
Finally |
Nepovinné. Finally Blok se vždy spustí, když provádění opustí jakoukoli část Try...Catch příkazu. |
finallyStatements |
Nepovinné. Příkazy, které se spustí po dokončení veškerého dalšího zpracování chyb. |
End Try |
Ukončí Try...Catch...Finally strukturu. |
Poznámky
Pokud očekáváte, že během konkrétní části kódu může dojít k určité výjimce, vložte kód do Try
bloku a pomocí Catch
bloku zachovejte kontrolu a zpracování výjimky, pokud k ní dojde.
Příkaz Try…Catch
se skládá z Try
bloku následovaného jednou nebo více Catch
klauzulí, které určují obslužné rutiny pro různé výjimky. Pokud je v Try
bloku vyvolán výjimka, Visual Basic hledá Catch
příkaz, který zpracovává výjimku. Pokud se nenajde odpovídající Catch
příkaz, Visual Basic prozkoumá metodu, která volala aktuální metodu, a tak dále nahoru zásobník volání. Pokud se nenajde žádný Catch
blok, Visual Basic zobrazí neošetřenou zprávu o výjimce uživateli a zastaví spuštění programu.
V příkazu můžete použít více než jeden Catch
příkaz Try…Catch
. Pokud to uděláte, pořadí Catch
klauzulí je významné, protože jsou zkoumány v pořadí. Catch konkrétnější výjimky před méně specifickými výjimkami.
Následující Catch
podmínky příkazu jsou nejméně specifické a budou všechny catch výjimky odvozené z Exception třídy. Po zachycení všech konkrétních výjimek, které očekáváte, byste měli obvykle použít jednu z těchto variant jako poslední Catch
blok struktury Try...Catch...Finally
. Tok řízení se nikdy nemůže spojit s blokem, který následuje za některou Catch
z těchto variant.
Jedná se
type
Exception
například o:Catch ex As Exception
Příkaz nemá žádnou
exception
proměnnou, například:Catch
Try…Catch…Finally
Když je příkaz vnořený do jiného Try
bloku, Visual Basic nejprve prozkoumá každý Catch
příkaz v nejvnitřnějším Try
bloku. Pokud se nenajde žádný odpovídající Catch
příkaz, vyhledávání pokračuje na Catch
příkazy vnějšího Try…Catch…Finally
bloku.
Místní proměnné z Try
bloku nejsou v bloku k dispozici Catch
, protože jsou samostatné bloky. Pokud chcete použít proměnnou ve více než jednom bloku, deklarujte proměnnou mimo Try...Catch...Finally
strukturu.
Tip
Příkaz Try…Catch…Finally
je k dispozici jako fragment kódu IntelliSense. Ve Správci fragmentů kódu rozbalte vzory kódu – If, For Each, TryCatch, Property atd. Pak zpracování chyb (výjimky). Další informace najdete v tématu Fragmenty kódu.
Blok Finally
Pokud máte jeden nebo více příkazů, které se musí spustit před ukončením Try
struktury, použijte Finally
blok. Řízení se předejde do Finally
bloku těsně před tím, než vyjde ze Try…Catch
struktury. To platí i v případě, že dojde k výjimce kdekoli uvnitř Try
struktury.
Finally
Blok je užitečný pro spuštění libovolného kódu, který se musí spustit, i když dojde k výjimce. Řízení se předává do Finally
bloku bez ohledu na to, jak Try...Catch
se blok ukončí.
Kód v Finally
bloku se spustí i v případě, že váš kód narazí na Return
příkaz v bloku Try
nebo Catch
bloku. Ovládací prvek nepřejde z odpovídajícího Try
bloku do Catch
odpovídajícího Finally
bloku v následujícíchpřípadechch
Příkaz End je zjištěn v
Try
bloku neboCatch
v bloku.A StackOverflowException je vyvolán v
Try
bloku neboCatch
v bloku.
Není platné explicitně převést provádění do Finally
bloku. Přenos spuštění z Finally
bloku není platný, s výjimkou výjimky.
Try
Pokud příkaz neobsahuje aspoň jeden Catch
blok, musí obsahovat Finally
blok.
Tip
Pokud nemáte konkrétní catch výjimky, Using
příkaz se chová jako Try…Finally
blok a zaručuje odstranění prostředků bez ohledu na to, jak blok ukončíte. To platí i při neošetřené výjimce. Další informace naleznete v tématu Using – příkaz.
Argument výjimky
Argument Catch
bloku exception
je instance Exception třídy nebo třídy, která je odvozena od Exception
třídy. Instance Exception
třídy odpovídá chybě, ke které došlo v Try
bloku.
Vlastnosti objektu Exception
pomáhají identifikovat příčinu a umístění výjimky. StackTrace Například vlastnost uvádí volané metody, které vedly k výjimce, a pomáhá najít, kde došlo k chybě v kódu. Message vrátí zprávu, která popisuje výjimku. HelpLink vrátí odkaz na přidružený soubor nápovědy. InnerExceptionException
vrátí objekt, který způsobil aktuální výjimku, nebo vrátíNothing
, pokud neexistuje žádný původní Exception
.
Důležité informace o použití Try…Catch
příkazu
Try…Catch
Příkaz použijte pouze k označení výskytu neobvyklých nebo neočekážených událostí programu. Mezi důvody patří:
Zachytávání výjimek za běhu vytváří další režii a pravděpodobně bude pomalejší než kontrola před kontrolou, aby nedocházelo k výjimkám.
Catch
Pokud se blok nezpracuje správně, výjimka nemusí být uživatelům nahlášena správně.Zpracovánívýjimekch
Vždy nepotřebujete Try…Catch
příkaz ke kontrole podmínky, která by pravděpodobně nastala. Následující příklad zkontroluje, zda soubor existuje před pokusem o jeho otevření. To snižuje potřebu zachycení výjimky vyvolané metodou 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
Ujistěte se, že kód v Catch
blocích může uživatelům správně hlásit výjimky, ať už prostřednictvím protokolování bezpečného pro přístup z více vláken nebo vhodných zpráv. V opačném případě můžou výjimky zůstat neznámé.
Asynchronní metody
Pokud metodu označíte modifikátorem Async , můžete v metodě použít operátor Await . Příkaz s operátorem Await
pozastaví provádění metody, dokud se neskončí očekávaný úkol. Úkol představuje probíhající práci. Když se úloha přidružená k operátoru Await
dokončí, provádění se obnoví ve stejné metodě. Další informace naleznete v tématu Tok řízení v asynchronních programech.
Úloha vrácená asynchronní metodou může končit chybným stavem, což značí, že se dokončila kvůli neošetřené výjimce. Úkol může také končit zrušeným stavem, což vede OperationCanceledException
k vyvolání výrazu await. Do catch některého typu výjimky umístěte Await
výraz přidružený k úkolu do Try
bloku a catch výjimku v Catch
bloku. Příklad najdete dále v tomto tématu.
Úkol může být v chybném stavu, protože za jeho selhání zodpovídá více výjimek. Například úkol může být výsledkem volání Task.WhenAll. Když na takový úkol čekáte, chycená výjimka je pouze jednou z výjimek a nemůžete předpovědět, která výjimka se zachytí. Příklad najdete dále v tomto tématu.
Výraz Await
nemůže být uvnitř Catch
bloku nebo Finally
bloku.
Iterátory
Funkce iterátoru nebo Get
příslušenství provádí vlastní iteraci v kolekci. Iterátor používá příkaz Yield k vrácení každého prvku kolekce po jednom. Funkci iterátoru můžete volat pomocí funkce For Each... Next – příkaz.
Příkaz Yield
může být uvnitř Try
bloku. Try
Blok, který obsahuje Yield
příkaz, může obsahovat Catch
bloky a může obsahovat Finally
blok. Příklad najdete v tématu Try Bloky.
Příkaz Yield
nemůže být uvnitř Catch
bloku nebo Finally
bloku.
For Each
Pokud tělo (mimo funkci iterátoru) vyvolá výjimku, Catch
nespustí se blok ve funkci iterátoru, ale Finally
spustí se blok ve funkci iterátoru. Blok Catch
uvnitř funkce iterátoru zachytává pouze výjimky, ke kterým dochází uvnitř funkce iterátoru.
Částečné vztahy důvěryhodnosti
V situacích s částečnou důvěryhodností, jako je například aplikace hostovaná ve sdílené síťové složce, Try...Catch...Finally
nedojde catch k výjimkám zabezpečení, ke kterým dochází před vyvolání metody obsahující volání. Následující příklad, když ho umístíte do sdílené složky serveru a spustíte odsud, dojde k chybě System.Security.SecurityException: Požadavek se nezdařil. Další informace o výjimkách zabezpečení najdete ve SecurityException třídě.
Try
Process.Start("http://www.microsoft.com")
Catch ex As Exception
Console.WriteLine("Can't load Web page" & vbCrLf & ex.Message)
End Try
V takové situaci s částečnou důvěrou musíte vložit Process.Start
příkaz do samostatného Sub
. Počáteční volání se Sub
nezdaří. To mu umožní Try...Catch
catch před spuštěním Sub
souboru, který obsahuje Process.Start
, a vygenerované výjimky zabezpečení.
Příklady
Struktura Try...Catch...Finally
Následující příklad znázorňuje strukturu Try...Catch...Finally
příkazu.
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
Výjimka v metodě volané Try
z bloku
V následujícím příkladu metoda CreateException
vyvolá NullReferenceException
. Kód, který vygeneruje výjimku, není v Try
bloku. Proto metoda nezpracuje CreateException
výjimku. Metoda RunSample
zpracovává výjimku, protože volání CreateException
metody je v Try
bloku.
Příklad obsahuje Catch
příkazy pro několik typů výjimek seřazených od nejvýraznějších po nejobecnější.
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
Příkaz Catch When
Následující příklad ukazuje, jak použít Catch When
příkaz k filtrování podmíněného výrazu. Pokud se podmíněný výraz vyhodnotí jako True
, kód v Catch
bloku se spustí.
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
Vnořené Try
příkazy
Následující příklad obsahuje Try…Catch
příkaz, který je obsažen v Try
bloku. Vnitřní Catch
blok vyvolá výjimku, která má jeho InnerException
vlastnost nastavenou na původní výjimku. Vnější Catch
blok hlásí vlastní výjimku a vnitřní výjimku.
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
Zpracování výjimek pro asynchronní metody
Následující příklad znázorňuje zpracování výjimek pro asynchronní metody. Na catch výjimku, která se vztahuje na asynchronní úlohu, Await
je výraz v Try
bloku volajícího a výjimka je zachycena Catch
v bloku.
Odkomentujte řádek v příkladu a předveďte Throw New Exception
zpracování výjimek. Výjimka je zachycena Catch
v bloku, vlastnost úkolu IsFaulted
je nastavena na True
a vlastnost úkolu Exception.InnerException
je nastavena na výjimku.
Odkomentujte Throw New OperationCancelledException
řádek, abyste ukázali, co se stane, když zrušíte asynchronní proces. Výjimka je zachycena Catch
v bloku a vlastnost úkolu IsCanceled
je nastavena na True
. Nicméně za určitých podmínek, které se nevztahují na tento příklad, je nastavena True
na a IsCanceled
je nastavena na False
. IsFaulted
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
Zpracování více výjimek v asynchronních metodách
Následující příklad znázorňuje zpracování výjimek, kdy více úloh může vést k několika výjimkám. Blok Try
obsahuje Await
výraz pro vrácenou úlohu Task.WhenAll . Úkol je dokončen, když jsou dokončeny tři úkoly, na které Task.WhenAll se použijí.
Každý ze tří úkolů způsobí výjimku. Blok Catch
iteruje prostřednictvím výjimek, které jsou nalezeny ve Exception.InnerExceptions
vlastnosti úkolu, který Task.WhenAll
vrátil.
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