Asynchronní programování s modifikátorem Async a operátoru Await (Visual Basic)
Pomocí asynchronního programování se můžete vyhnout kritickým bodům a zlepšit celkovou rychlost reakce aplikace. Tradiční techniky pro psaní asynchronních aplikací však mohou být složité, takže je obtížné je napsat, ladit a udržovat.
Visual Studio 2012 představil zjednodušený přístup, asynchronní programování, které využívá asynchronní podporu v .NET Framework 4,5 a vyšší a také v prostředí Windows Runtime. Kompilátor na sebe přejímá náročnou práci, kterou vykonával vývojář, a vaše aplikace si zachovává logickou strukturu, která se podobá synchronnímu kódu. Výsledkem je, že získáte všechny výhody asynchronního programování při pouhém zlomku úsilí.
Toto téma obsahuje přehled kdy a jak použít asynchronní programování a obsahuje odkazy na témata podpory, která obsahují podrobné informace a příklady.
Asynchronní funkce vylepšuje rychlost odezvy.
Asynchronie je nezbytná pro aktivity, které mohou potenciálně blokovat, například pokud vaše aplikace přistupuje na web. Přístup k webovému prostředku je někdy pomalý nebo zpožděný. Pokud je taková činnost blokována v rámci synchronního procesu, musí čekat celá aplikace. U asynchronního procesu může aplikace pokračovat v další práci, která nezávisí na webovém prostředku, dokud neskončí potenciálně blokující úloha.
Následující tabulka ukazuje typické oblasti, kde asynchronní programování zlepšuje rychlost reakce. uvedená rozhraní api z .NET Framework 4,5 a prostředí Windows Runtime obsahují metody, které podporují asynchronní programování.
| Oblast aplikace | Podpora rozhraní API, která obsahují asynchronní metody |
|---|---|
| Webový přístup | HttpClient, SyndicationClient |
| Práce se soubory | StorageFile, StreamWriter, StreamReader, XmlReader |
| Práce s obrázky | MediaCapture, BitmapEncoder, BitmapDecoder |
| Programování WCF | Synchronní a asynchronní operace |
Asynchronie je obzvláště užitečná pro aplikace, které přistupují k vláknu UI, protože všechny aktivity související s uživatelským rozhraním obvykle sdílí jedno vlákno. Pokud je jakýkoli proces blokován v synchronní aplikaci, jsou blokovány všechny. Vaše aplikace přestane reagovat a můžete dojít k závěru, že selhala, i když místo toho čeká.
Při použití asynchronních metod bude aplikace i nadále odpovídat na uživatelské rozhraní. Pokud nechcete čekat na dokončení, můžete změnit velikost nebo minimalizovat okno, například můžete zavřít aplikaci.
Asynchronní přístup přidává ekvivalent automatického přenosu do seznamu možností, z nichž můžete vybírat při vytváření asynchronní operace. To znamená, že získáte všechny výhody tradičního asynchronního programování, ale s mnohem menším úsilím ze strany vývojáře.
Asynchronní metody se snáze zapisují
klíčová slova Async a Await v Visual Basic jsou srdcem asynchronního programování. pomocí těchto dvou klíčových slov můžete použít prostředky v .NET Framework nebo prostředí Windows Runtime k vytvoření asynchronní metody téměř stejně snadno, jako vytváříte synchronní metodu. Asynchronní metody, které definujete pomocí Async a Await jsou označovány jako asynchronní metody.
Následující příklad ukazuje asynchronní metodu. Téměř vše v rámci kódu by vám mělo být zcela známé. Komentáře volají funkce, které jste přidali při tvorbě asynchronie.
na konci tohoto tématu můžete najít úplný ukázkový soubor Windows Presentation Foundation (WPF) a můžete si stáhnout ukázku z Async sample: příklad z tématu "asynchronní programování s async a Await".
' Three things to note about writing an Async Function:
' - The function has an Async modifier.
' - Its return type is Task or Task(Of T). (See "Return Types" section.)
' - As a matter of convention, its name ends in "Async".
Async Function AccessTheWebAsync() As Task(Of Integer)
Using client As New HttpClient()
' Call and await separately.
' - AccessTheWebAsync can do other things while GetStringAsync is also running.
' - getStringTask stores the task we get from the call to GetStringAsync.
' - Task(Of String) means it is a task which returns a String when it is done.
Dim getStringTask As Task(Of String) =
client.GetStringAsync("https://docs.microsoft.com/dotnet")
' You can do other work here that doesn't rely on the string from GetStringAsync.
DoIndependentWork()
' The Await operator suspends AccessTheWebAsync.
' - AccessTheWebAsync does not continue until getStringTask is complete.
' - Meanwhile, control returns to the caller of AccessTheWebAsync.
' - Control resumes here when getStringTask is complete.
' - The Await operator then retrieves the String result from getStringTask.
Dim urlContents As String = Await getStringTask
' The Return statement specifies an Integer result.
' A method which awaits AccessTheWebAsync receives the Length value.
Return urlContents.Length
End Using
End Function
Pokud nemá AccessTheWebAsync žádnou práci, kterou může provést mezi voláním GetStringAsync a čekáním na jeho dokončení, můžete zjednodušit kód voláním a čekáním v následujícím jediném příkazu.
Dim urlContents As String = Await client.GetStringAsync()
Následující charakteristiky shrnují, co dělá předchozí příklad asynchronní metodou:
Signatura metody obsahuje
Asyncmodifikátor.Název asynchronní metody končí podle konvence příponou „Async“.
Návratový typ je jeden z následujících typů:
- Úkol (Of TResult) , pokud vaše metoda má návratový příkaz, ve kterém je operand typu TResult.
- Task Pokud vaše metoda nemá návratový příkaz nebo má návratový příkaz bez operandu.
- Sub , pokud píšete asynchronní obslužnou rutinu události.
Další informace naleznete v části „Návratové typy a parametry“ dále v tomto tématu.
Metoda obvykle zahrnuje nejméně jeden očekávaný výraz, který označuje bod, kde metoda nemůže pokračovat, dokud očekávaná asynchronní operace nebude dokončena. Během této doby je metoda pozastavena a ovládací prvek se vrátí volajícímu metody. Další část tohoto tématu ukazuje, co se stane v okamžiku pozastavení.
V asynchronních metodách používáte zadaná klíčová slova a typy pro označení, jakou akci chcete provést, a kompilátor udělá zbytek, včetně udržování přehledu o tom, co musí nastat, když se řízení vrátí do bodu „await“ pozastavené metody. Některé běžné procesy, jako je zpracování smyček a výjimek, může být v tradičním asynchronním kódu obtížné zpracovat. V asynchronní metodě zapisujete tyto prvky podobně, jako byste to udělali v synchronním řešení, a problém je vyřešen.
další informace o asynchronii v předchozích verzích .NET Framework naleznete v tématu TPL a tradiční .NET Framework asynchronní programování.
Co se stane v asynchronní metodě
Nejdůležitějším principem, který je třeba pochopit v asynchronním programování, je, jak ovládat přesuny toků od metody k metodě. Následující diagram vás provede procesem:

Čísla v diagramu odpovídají následujícím krokům:
Obslužná rutina události volá a očekává
AccessTheWebAsyncasynchronní metodu.AccessTheWebAsyncvytvoří HttpClient instanci a zavolá GetStringAsync asynchronní metodu pro stažení obsahu webu jako řetězce.Dojde k tomu
GetStringAsync, že se něco pozastaví. Možná je třeba vyčkat na dokončení stahování nebo jiné blokující aktivity na webu. Aby nedocházelo k blokování prostředků,GetStringAsyncposkytne řízení volajícímu,AccessTheWebAsync.GetStringAsyncVrátí úlohu (Of TResult) , kde TResult je řetězec, aAccessTheWebAsyncpřiřadí úlohugetStringTaskproměnné. Úkol představuje pokračující proces pro voláníGetStringAsyncs závazkem vytvořit skutečnou řetězcovou hodnotu po dokončení práce.Vzhledem k tomu
getStringTask, že se ještě nečekalo,AccessTheWebAsyncmůže pokračovat v jiné práci, která nezávisí na konečném výsledku zGetStringAsync. Tato práce je reprezentována voláním synchronní metodyDoIndependentWork.DoIndependentWorkje synchronní metoda, která provede svou práci a vrátí jejímu volajícímu.AccessTheWebAsyncnemá dostatek práce, kterou může dělat bez výsledku zgetStringTask.AccessTheWebAsyncDále chce vypočítat a vrátit délku staženého řetězce, ale metoda nemůže tuto hodnotu vypočítat, dokud metoda nemá řetězec.Proto
AccessTheWebAsyncpomocí operátoru await pozastaví svůj průběh a vrátí řízení metodě, která je volánaAccessTheWebAsync.AccessTheWebAsyncVrátí hodnotuTask(Of Integer)volajícímu. Úloha představuje slib vyrábět celé číslo výsledku, který má délku staženého řetězce.Poznámka
Pokud
GetStringAsync(a tedygetStringTask) je dokončena před tímAccessTheWebAsync, než očekává, ovládací prvek zůstane vAccessTheWebAsync. Náklady na pozastavení a návrat doAccessTheWebAsyncby byly nevyužité, pokud se pojmenovaný asynchronní proces (getStringTask) již dokončil a AccessTheWebSync nebude nemusí čekat na konečný výsledek.Uvnitř volajícího (v tomto případě obslužná rutina události) bude vzor zpracování pokračovat. Volající může provést další práci, která nezávisí na výsledku před čekáním na
AccessTheWebAsyncvýsledek, nebo volající může očekávat okamžitě. Obslužná rutina události čeká naAccessTheWebAsyncaAccessTheWebAsyncčeká naGetStringAsync.GetStringAsyncdokončí a vytvoří výsledek řetězce. Výsledek řetězce není vrácen volánímGetStringAsynczpůsobem, který by mohl očekávat. (Nezapomeňte, že metoda již vrátila úlohu v kroku 3.) Místo toho je výsledek řetězce uložen v úkolu, který představuje dokončení metodygetStringTask. Operátor await načte výsledek zgetStringTask. Příkaz přiřazení přiřadí načtený výsledek dourlContents.Když
AccessTheWebAsyncmá výsledek řetězce, metoda může vypočítat délku řetězce. PakAccessTheWebAsyncje práce také dokončena a může pokračovat obslužná rutina čekající události. V úplném příkladu na konci tématu si můžete potvrdit, že obslužná rutina události načte a vytiskne hodnotu výsledné délky.
Pokud jste v oblasti asynchronního programování nováčky, zvažte rozdíl mezi synchronním a asynchronním chováním. Synchronní metoda je vrácena, jakmile je její práce dokončena (krok 5), ale asynchronní metoda vrátí hodnotu úlohy, když je její práce pozastavena (kroky 3 a 6). Když asynchronní metoda nakonec dokončí svou práci, je úloha označena jako dokončená a výsledek, pokud existuje, je uložen v úloze.
další informace o toku řízení naleznete v tématu control Flow in Async programs (Visual Basic).
Asynchronní metody rozhraní API
Možná vás zajímá, kde najít metody, jako je například GetStringAsync Podpora asynchronního programování. .NET Framework 4,5 nebo vyšší obsahuje mnoho členů, které pracují s Async a Await . Tyto členy můžete rozpoznat pomocí přípony "Async", která je připojena k názvu člena a návratový typ Task nebo úkol (Of TResult). Například System.IO.Stream Třída obsahuje metody, jako CopyToAsync , a ReadAsync WriteAsync vedle synchronních metod CopyTo , Read a Write .
prostředí Windows Runtime také obsahuje mnoho metod, které lze použít s Async aplikacemi a Await v Windows aplikacích. další informace a příklady metod naleznete v tématu volání asynchronních rozhraní api v jazyce C# nebo Visual Basic, asynchronní programování (prostředí Windows Runtime aplikace)a WhenAny: přemostění mezi .NET Framework a prostředí Windows Runtime.
Vláken
Asynchronní metody mají být neblokující operace. AwaitVýraz v asynchronní metodě neblokuje aktuální vlákno, zatímco je spuštěn očekávaný úkol. Namísto toho se výraz zaregistruje pro zbývající metody jako pokračování a vrátí řízení volajícímu asynchronní metody.
Async Await Klíčová slova a nezpůsobí vytvoření dalších vláken. Asynchronní metody nevyžadují multithreading, protože asynchronní metoda není spuštěna ve vlastním vlákně. Metoda pracuje na aktuálním kontextu synchronizace a používá čas ve vlákně pouze v případě, že je metoda aktivní. Můžete použít Task.Run pro přesun práce vázané na procesor do vlákna na pozadí, ale vlákno na pozadí nepomůže s procesem, který právě čeká na zpřístupnění výsledků.
Asynchronní přístup při asynchronním programování se doporučuje v téměř každém případě existujících přístupů. Konkrétně tento přístup je lepší než BackgroundWorker pro operace vázané na vstup a výstup, protože kód je jednodušší a nemusíte se chránit před konflikty časování. V kombinaci s Task.Run je asynchronní programování lepší než BackgroundWorker pro operace vázané na procesor, protože asynchronní programování odděluje koordinační údaje o spuštění kódu z práce, která se Task.Run přenáší do fondu.
Async a await
Pokud určíte, že metoda je asynchronní metodou pomocí modifikátoru Async , povolíte následující dvě možnosti.
Označená asynchronní metoda může použít operátor await k určení bodů zavěšení. Operátor await sděluje kompilátoru, že s asynchronními metodami nelze za daným bodem pokračovat, dokud nebude dokončen očekávaný asynchronní proces. Během této doby se ovládací prvek vrátí volajícímu asynchronní metody.
Pozastavení asynchronní metody ve
Awaitvýrazu nepředstavuje příkaz exit z metody aFinallybloky nejsou spuštěny.Samotná označená asynchronní metoda může být očekávána metodami, které ji volaly.
Asynchronní metoda obvykle obsahuje jeden nebo více výskytů Await operátoru, ale absence Await výrazů nezpůsobí chybu kompilátoru. Pokud asynchronní metoda nepoužívá Await operátor k označení bodu pozastavení, metoda se spustí jako synchronní metoda bez ohledu na Async modifikátor. Kompilátor u takových metod zahlásí upozornění.
Async a Await jsou kontextová klíčová slova. Další informace a příklady naleznete v následujících tématech:
Návratové typy a parametry
při programování .NET Framework asynchronní metoda obvykle vrací Task úlohu (Of TResult). V rámci asynchronní metody Await je operátor použit pro úkol, který je vrácen z volání jiné asynchronní metody.
Pokud metoda obsahuje příkaz return , který určuje operand typu, je třeba zadat úlohu (Of TResult) jako návratový typ TResult .
Použijete Task jako návratový typ, pokud metoda nemá žádný návratový příkaz nebo má návratový příkaz, který nevrací operand.
Následující příklad ukazuje, jak deklarovat a volat metodu, která vrací úlohu (Of TResult) nebo Task :
' Signature specifies Task(Of Integer)
Async Function TaskOfTResult_MethodAsync() As Task(Of Integer)
Dim hours As Integer
' . . .
' Return statement specifies an integer result.
Return hours
End Function
' Calls to TaskOfTResult_MethodAsync
Dim returnedTaskTResult As Task(Of Integer) = TaskOfTResult_MethodAsync()
Dim intResult As Integer = Await returnedTaskTResult
' or, in a single statement
Dim intResult As Integer = Await TaskOfTResult_MethodAsync()
' Signature specifies Task
Async Function Task_MethodAsync() As Task
' . . .
' The method has no return statement.
End Function
' Calls to Task_MethodAsync
Task returnedTask = Task_MethodAsync()
Await returnedTask
' or, in a single statement
Await Task_MethodAsync()
Každá vrácená úloha představuje probíhající práci. Úloha zapouzdřuje informace o stavu asynchronního procesu a posléze buď konečný výsledek z procesu, nebo výjimku, kterou proces vyvolá v případě neúspěchu.
Asynchronní metoda může být také Sub metoda. Tento návratový typ slouží primárně k definování obslužných rutin událostí, kde je požadován návratový typ. Asynchronní obslužné rutiny událostí často slouží jako výchozí bod pro asynchronní programy.
Asynchronní metodu, která je Sub procedura, nemůže být očekávána a volající nemůže zachytit žádné výjimky, které metoda vyvolá.
Asynchronní metoda nemůže deklarovat parametry ByRef , ale metoda může volat metody, které mají tyto parametry.
Další informace a příklady naleznete v tématu Async Return Types (Visual Basic). Další informace o tom, jak zachytit výjimky v asynchronních metodách, naleznete v tématu Try... Zachytit... Finally – příkaz.
asynchronní rozhraní api v prostředí Windows Runtime programování mají jeden z následujících návratových typů, které jsou podobné úlohám:
- IAsyncOperation (Of TResult), který odpovídá úloze (Of TResult)
- IAsyncAction, který odpovídá Task
- IAsyncActionWithProgress (of TProgress)
- IAsyncOperationWithProgress (Of TResult, TProgress)
Další informace a příklad najdete v tématu volání asynchronních rozhraní API v jazyce C# nebo Visual Basic.
Konvence pojmenování
Podle konvence připojíte "Async" k názvům metod, které mají Async modifikátor.
Můžete ignorovat konvenci, kde událost, základní třída a rozhraní smlouvy navrhují odlišný název. Například byste neměli přejmenovat běžné obslužné rutiny událostí, jako je například Button1_Click .
Související témata a ukázky (Visual Studio)
Kompletní příklad
následující kód je soubor MainWindow. xaml. vb z aplikace Windows Presentation Foundation (WPF), kterou popisuje toto téma. Ukázku si můžete stáhnout z části Async Sample: příklad z "asynchronní programování s Async a await".
Imports System.Net.Http
' Example that demonstrates Asynchronous Progamming with Async and Await.
' It uses HttpClient.GetStringAsync to download the contents of a website.
' Sample Output:
' Working . . . . . . .
'
' Length of the downloaded string: 39678.
Class MainWindow
' Mark the event handler with Async so you can use Await in it.
Private Async Sub StartButton_Click(sender As Object, e As RoutedEventArgs)
' Call and await immediately.
' StartButton_Click suspends until AccessTheWebAsync is done.
Dim contentLength As Integer = Await AccessTheWebAsync()
ResultsTextBox.Text &= $"{vbCrLf}Length of the downloaded string: {contentLength}.{vbCrLf}"
End Sub
' Three things to note about writing an Async Function:
' - The function has an Async modifier.
' - Its return type is Task or Task(Of T). (See "Return Types" section.)
' - As a matter of convention, its name ends in "Async".
Async Function AccessTheWebAsync() As Task(Of Integer)
Using client As New HttpClient()
' Call and await separately.
' - AccessTheWebAsync can do other things while GetStringAsync is also running.
' - getStringTask stores the task we get from the call to GetStringAsync.
' - Task(Of String) means it is a task which returns a String when it is done.
Dim getStringTask As Task(Of String) =
client.GetStringAsync("https://docs.microsoft.com/dotnet")
' You can do other work here that doesn't rely on the string from GetStringAsync.
DoIndependentWork()
' The Await operator suspends AccessTheWebAsync.
' - AccessTheWebAsync does not continue until getStringTask is complete.
' - Meanwhile, control returns to the caller of AccessTheWebAsync.
' - Control resumes here when getStringTask is complete.
' - The Await operator then retrieves the String result from getStringTask.
Dim urlContents As String = Await getStringTask
' The Return statement specifies an Integer result.
' A method which awaits AccessTheWebAsync receives the Length value.
Return urlContents.Length
End Using
End Function
Sub DoIndependentWork()
ResultsTextBox.Text &= $"Working . . . . . . .{vbCrLf}"
End Sub
End Class