Programowanie asynchroniczne z funkcją Async i Await (Visual Basic)

Możesz uniknąć problemów z wydajnością i poprawić ogólny czas odpowiedzi aplikacji, stosując programowanie asynchroniczne. Jednak tradycyjne techniki pisania aplikacji asynchronicznych mogą być skomplikowane, przez co trudne do pisania, debugowania i konserwacji.

Visual Studio 2012 r. wprowadzono uproszczone podejście, programowanie asynchroniczne, które wykorzystuje asynchroniczne wsparcie w .NET Framework 4.5 i nowszych, a także w środowisko wykonawcze systemu Windows. Kompilator wykonuje trudną pracę, którą kiedyś wykonywał programista, a aplikacja zachowuje strukturę logiczną przypominającą kod synchroniczny. W efekcie masz wszystkie korzyści wynikające z programowania asynchronicznego przy ułamkowym nakładzie pracy.

Ten temat zawiera omówienie, kiedy i jak stosować programowanie async oraz zawiera łącza do tematów zawierających szczegółowe informacje oraz przykłady.

Asynchroniczne poprawia czas reakcji

Asynchroniczność jest istotna dla działań, które mogą powodować blokowanie, na przykład, gdy aplikacja uzyskuje dostęp do sieci Web. Dostęp do zasobów sieci Web bywa powolny lub opóźniony. Jeśli takie działanie jest zablokowane w procesie synchronicznym, cała aplikacji musi czekać. W procesie asynchronicznym aplikacja może kontynuować wykonywanie innych zadań, które nie są zależne od zasobów sieci Web, do momentu zakończeniem zadania mogącego powodować blokowanie.

W poniższej tabeli przedstawiono typowe obszary, w których programowanie asynchroniczne poprawia czas odpowiedzi. Wymienione interfejsy API z .NET Framework 4.5 i środowisko wykonawcze systemu Windows zawierają metody obsługujące programowanie asynchroniczne.

Obszar aplikacji Obsługa interfejsów API, która obejmuje metody asynchroniczne
Web access HttpClient, SyndicationClient
Praca z plikami StorageFile, StreamWriter, StreamReader, XmlReader
Praca z obrazami MediaCapture, BitmapEncoder, BitmapDecoder
Programowanie WCF Operacje synchroniczne i asynchroniczne

Asynchroniczność okazuje się szczególnie cenna w przypadku aplikacji, które mają dostęp do wątku interfejsu użytkownika, ponieważ wszystkie działania związane z interfejsem użytkownika korzystają zazwyczaj z jednego wątku. Jeśli w aplikacji synchronicznej jest zablokowany jakikolwiek proces, zablokowane są wszystkie procesy. Aplikacja przestanie odpowiadać i możesz dojść do wniosku, że uległa awarii, a tymczasem może po prostu być w stanie oczekiwania.

Kiedy używasz metod asynchronicznych, aplikacja dalej odpowiada interfejsowi użytkownika. Możesz przykładowo zmienić rozmiar lub zminimalizować aplikację lub możesz ją zamknąć, jeżeli nie chcesz czekać aż zakończy zadanie.

Podejście async oferuje również odpowiednik automatycznego przejścia do listy opcji do wybrania przy projektowaniu operacji asynchronicznych. Oznacza to, że można korzystać z wszystkich zalet tradycyjnego programowania asynchronicznego, ale przy znacznie mniejszym nakładzie pracy programisty.

Metody asynchroniczne są łatwiejsze do zapisu

Słowa kluczowe Async i Await w Visual Basic są sercem programowania asynchronicznego. Używając tych dwóch słów kluczowych, możesz użyć zasobów w .NET Framework lub środowisko wykonawcze systemu Windows, aby utworzyć metodę asynchroniczną niemal tak łatwo, jak tworzysz metodę synchroniczną. Metody asynchroniczne definiowane przy użyciu metody Async i Await są określane jako metody asynchroniczne.

W poniższym przykładzie przedstawiono metodę async. Prawie wszystko w kodzie powinno wyglądać znajomo. Komentarze wywołują funkcje dodawane przez użytkownika w celu uzyskania asynchroniczności.

Pełny plik przykładowy Windows Presentation Foundation (WPF) można znaleźć na końcu tego tematu i pobrać przykład z przykładu Async Sample: Example from "Asynchronous Programming with Async and Await" (Asynchroniczne programowanie za pomocą asynchronicznego i 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

Jeśli AccessTheWebAsync nie ma żadnej pracy, którą może wykonać między wywołaniem GetStringAsync i oczekiwaniem na ukończenie, możesz uprościć kod, wywołując i oczekując na następującą pojedynczą instrukcję.

Dim urlContents As String = Await client.GetStringAsync()

Poniższe charakterystyki zawierają podsumowanie tego, co sprawia, że poprzedni przykład jest metodą asynchronikową:

  • Podpis metody zawiera Async modyfikator.

  • Nazwa metody async kończy się zwyczajowo sufiksem „Async”.

  • Zwracany typ może być jednym z następujących:

    • Task(Of TResult), jeśli metoda ma instrukcję return, w której operand ma typ TResult.
    • Task jeśli metoda nie ma instrukcji return lub ma instrukcję return bez operandu.
    • Sub , jeśli piszesz asynchroniczny program obsługi zdarzeń.

    Aby uzyskać więcej informacji, zobacz „Typy zwracane i parametry” w dalszej części tego tematu.

  • Metoda zazwyczaj zawiera co najmniej jedno wyrażenie „await”, które oznacza punkt, w którym metoda nie może kontynuować pracy do czasu ukończenia operacji asynchronicznej. W tym czasie metoda jest zawieszona, a sterowanie powraca do obiektu wywołującego metodę. Następna sekcji tego tematu przedstawia, co się dzieje w punkcie zawieszenia.

W metodzie asynchronicznej używasz podanych słów kluczowych i typów w celu wskazania, co chcesz zrobić, a kompilator zajmie się resztą, w tym śledzeniem tego, co musi się zdarzyć, gdy sterowanie powraca do punktu oczekiwania w metodzie zawieszonej. Niektóre procesy, takie jak pętle i obsługa wyjątków, mogą być trudne do obsłużenia w tradycyjnym kodzie asynchronicznym. W metodzie asynchronicznej wpisujesz te elementy podobnie jak w rozwiązaniu synchronicznym i problem rozwiązany.

Aby uzyskać więcej informacji na temat asynchronii w poprzednich wersjach .NET Framework, zobacz TPL i Tradycyjne .NET Framework Asynchroniczne programowanie.

Co się dzieje w metodzie asynchronicznej

Ważne jest, aby rozumieć programowanie asynchroniczne jako przepływ sterowania od metody do metody. Na poniższym diagramie przedstawiono proces:

Diagram that shows tracing an async program.

Liczby na diagramie odpowiadają następującym krokom:

  1. Program obsługi zdarzeń wywołuje i oczekuje na metodę AccessTheWebAsync asynchronizową.

  2. AccessTheWebAsynctworzy wystąpienie i wywołuje GetStringAsync metodę HttpClient asynchroniczną, aby pobrać zawartość witryny internetowej jako ciąg.

  3. Coś się dzieje w GetStringAsync tym zawiesza jego postęp. Być może metoda musi czekać na pobranie strony internetowej lub inne działanie blokujące. Aby uniknąć blokowania zasobów, GetStringAsync daje kontrolę nad obiektem wywołującym. AccessTheWebAsync

    GetStringAsync Zwraca zadanie (Z TResult), gdzie TResult jest ciągiem i AccessTheWebAsync przypisuje zadanie do zmiennej getStringTask . Zadanie reprezentuje bieżący proces wywołania metody GetStringAsync, z zobowiązaniem do wygenerowania rzeczywistej wartości ciągu po zakończeniu pracy.

  4. Ponieważ getStringTask nie oczekiwano jeszcze, AccessTheWebAsync może kontynuować inne prace, które nie zależą od końcowego wyniku z GetStringAsyncprogramu . Ta praca jest reprezentowana przez wywołanie metody DoIndependentWorksynchronicznej .

  5. DoIndependentWork to metoda synchroniczna, która wykonuje swoją pracę i powraca do elementu wywołującego.

  6. AccessTheWebAsync zabrakło pracy, że może to zrobić bez wyniku z getStringTask. AccessTheWebAsync Następnie chce obliczyć i zwrócić długość pobranego ciągu, ale metoda nie może obliczyć tej wartości, dopóki metoda nie będzie mieć ciągu.

    AccessTheWebAsync W związku z tym używa operatora await, aby zawiesić jego postęp i kontrolować metodę o nazwie AccessTheWebAsync. AccessTheWebAsync zwraca obiekt do Task(Of Integer) elementu wywołującego. Zadanie przedstawia obietnicę utworzenia w wyniku liczby całkowitej, która jest długością pobranego ciągu.

    Uwaga

    Jeśli GetStringAsync (i dlatego getStringTask) zostanie ukończony przed AccessTheWebAsync jego oczekiwaniem, kontrolka pozostanie w AccessTheWebAsync. Koszt wstrzymania, a następnie powrotu do AccessTheWebAsync zostanie zmarnowany, jeśli wywołany proces asynchroniczny (getStringTask) () został już ukończony, a program AccessTheWebSync nie musi czekać na końcowy wynik.

    Przetwarzanie wzorca jest kontynuowane wewnątrz elementu wywołującego (programu obsługi zdarzeń w tym przykładzie). Obiekt wywołujący może wykonać inną pracę, która nie zależy od wyniku przed AccessTheWebAsync oczekiwaniem na ten wynik, lub obiekt wywołujący może oczekiwać natychmiast. Program obsługi zdarzeń czeka na AccessTheWebAsyncelement i AccessTheWebAsync czeka na GetStringAsync.

  7. GetStringAsync kończy i generuje wynik ciągu. Wynik ciągu nie jest zwracany przez wywołanie metody w sposób, który można oczekiwać GetStringAsync . (Pamiętaj, że metoda zwróciła już zadanie w kroku 3). Zamiast tego wynik ciągu jest przechowywany w zadaniu reprezentującym ukończenie metody getStringTask. Operator await pobiera wynik z getStringTaskelementu . Instrukcja przypisania przypisuje pobrany wynik do urlContents.

  8. Gdy AccessTheWebAsync wynik ciągu, metoda może obliczyć długość ciągu. Następnie praca jest AccessTheWebAsync również ukończona, a oczekujące procedury obsługi zdarzeń mogą być wznowione. W pełnym przykładzie na końcu tematu można zobaczyć, że program obsługi zdarzeń pobiera i drukuje wynikową wartość długości.

Jeśli dopiero zaczynasz przygodę z programowaniem asynchronicznym, zastanów się przez chwilę, jaka jest różnica między zachowaniem synchronicznym i asynchronicznym. Metoda synchroniczna kończy działanie, gdy praca jest zakończona (krok 5), natomiast metoda asynchroniczna zwraca wartość zadania, gdy jej praca jest zawieszona (kroki 3 i 6). Gdy metoda async ukończy pracę, zadanie jest oznaczane jako ukończone, a wynik, o ile istnieje, jest zapisywany w zadaniu.

Aby uzyskać więcej informacji na temat przepływu sterowania, zobacz Control Flow in Async Programs (Visual Basic).

Metody asynchroniczne interfejsu API

Być może zastanawiasz się, gdzie znaleźć metody, takie jak GetStringAsync ta obsługa programowania asynchronicznego. .NET Framework 4.5 lub nowszym zawiera wiele elementów członkowskich, które współpracują z elementami Async i Await. Można rozpoznać te elementy członkowskie za pomocą sufiksu "Async", który jest dołączony do nazwy elementu członkowskiego i typu zwracanego Task lub Task(Of TResult). Na przykład System.IO.Stream klasa zawiera metody, takie jak CopyToAsync, ReadAsynci WriteAsync obok metod CopyTosynchronicznych , Readi Write.

Środowisko wykonawcze systemu Windows zawiera również wiele metod, których można używać z aplikacjami Async i Await w Windows. Aby uzyskać więcej informacji i przykładowych metod, zobacz Wywoływanie asynchronicznych interfejsów API w języku C# lub Visual Basic, programowanie asynchroniczne(aplikacje środowisko wykonawcze systemu Windows) i WhenAny: mostkowanie między .NET Framework a aplikacjami środowisko wykonawcze systemu Windows.

Wątki

Metody async mają być operacjami niepowodującymi blokowania. Wyrażenie Await w metodzie asynchronicznej nie blokuje bieżącego wątku, gdy oczekiwane zadanie jest uruchomione. Zamiast tego, wyrażenie rejestruje pozostałą część metody jako kontynuację i przekazuje sterowanie do obiektu wywołującego metody async.

Słowa Async kluczowe i Await nie powodują utworzenia dodatkowych wątków. Metody asynchroniczne nie wymagają wielowątkowego, ponieważ metoda asynchroniczna nie jest uruchamiana we własnym wątku. Metoda działa w bieżącym kontekście synchronizacji i używa czasu wątku, tylko wtedy, gdy jest aktywna. Możesz użyć Task.Run polecenia , aby przenieść pracę związaną z procesorem CPU do wątku w tle, ale wątek w tle nie pomaga w procesie, który po prostu czeka na udostępnienie wyników.

Podejście async do programowania asynchronicznego jest preferowane prawie w każdym przypadku. W szczególności takie podejście jest lepsze niż BackgroundWorker w przypadku operacji związanych z operacjami we/wy, ponieważ kod jest prostszy i nie musisz chronić się przed warunkami wyścigu. W połączeniu z programem programowanie asynchroniczne jest lepsze niż BackgroundWorker w przypadku operacji związanych z Task.Runprocesorem CPU, ponieważ programowanie asynchroniczne oddziela szczegóły koordynacji uruchamiania kodu od pracy przesyłanej Task.Run do puli wątków.

Async i Await

Jeśli określisz, że metoda jest metodą asynchroniczna przy użyciu modyfikatora asynchronicznego , włączysz następujące dwie możliwości.

  • Oznaczona metoda asynchroniczna może użyć metody Await do wyznaczenia punktów zawieszenia. Operator await informuje kompilator, że metoda async nie może kontynuować działania do chwili zakończenia procesu asynchronicznego, na który oczekuje. W międzyczasie sterowanie powraca do obiektu wywołującego metodę async.

    Zawieszenie metody asynchronicznej w wyrażeniu Await nie stanowi wyjścia z metody , a Finally bloki nie są uruchamiane.

  • Metoda oznaczona jako async sama może być oczekiwana przez metody, które ją wywołują.

Metoda asynchroniczna zwykle zawiera jedno lub więcej wystąpień Await operatora, ale brak Await wyrażeń nie powoduje błędu kompilatora. Jeśli metoda asynchroniczna nie używa Await operatora do oznaczania punktu zawieszenia, metoda jest wykonywana jako metoda synchroniczna, pomimo Async modyfikatora. Kompilator generuje ostrzeżenia dla takich metod.

Async i Await są słowami kluczowymi kontekstowymi. Aby uzyskać więcej informacji i przykładów, zobacz następujący temat:

Zwracane typy i parametry

W .NET Framework programowania metoda asynchroniczna zwykle zwraca Task wartość lub task(Of TResult). Wewnątrz metody Await asynchronicznej operator jest stosowany do zadania zwróconego z wywołania do innej metody asynchronicznej.

Zadanie (Z TResult) należy określić jako typ zwracany, jeśli metoda zawiera instrukcję Return, która określa operand typu TResult.

Jest używany Task jako typ zwracany, jeśli metoda nie ma instrukcji return lub ma instrukcję return, która nie zwraca operandu.

W poniższym przykładzie pokazano, jak zadeklarować i wywołać metodę zwracającą metodę Task(Of TResult) lub :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żde zwracane zadanie reprezentuje zadanie pracy w toku. Zadanie zawiera informacje o stanie procesu asynchronicznego i, ostatecznie, albo ostatecznego wyniku procesu lub wyjątku, który zgłasza proces, jeśli się nie powiedzie.

Metoda asynchroniczna może być Sub również metodą . Ten zwracany typ jest używany głównie do definiowania procedur obsługi zdarzeń, w których wymagany jest typ zwracany. Programy async obsługi zdarzeń często służą jako punkt wejścia dla programów async.

Nie można oczekiwać metody asynchronicznej, której Sub nie można oczekiwać, a obiekt wywołujący nie może przechwycić żadnych wyjątków zgłaszanych przez metodę.

Metoda asynchroniczna nie może zadeklarować parametrów ByRef , ale metoda może wywoływać metody, które mają takie parametry.

Aby uzyskać więcej informacji i przykłady, zobacz Async Return Types (Visual Basic). Aby uzyskać więcej informacji na temat przechwytywania wyjątków w metodach asynchronicznych, zobacz Try... Złapać... Finally, instrukcja.

Asynchroniczne interfejsy API w programowaniu środowisko wykonawcze systemu Windows mają jeden z następujących typów zwracanych, które są podobne do zadań podrzędnych:

Aby uzyskać więcej informacji i przykład, zobacz Wywoływanie asynchronicznych interfejsów API w języku C# lub Visual Basic.

Konwencja nazewnictwa

Zgodnie z konwencją dołączasz ciąg "Async" do nazw metod, które mają Async modyfikator.

Można zignorować konwencję, gdy zdarzenie, klasa bazowa lub kontrakt interfejsu sugeruje inną nazwę. Na przykład nie należy zmieniać nazw typowych procedur obsługi zdarzeń, takich jak Button1_Click.

Powiązane tematy i przykłady (Visual Studio)

Tytuł Opis Przykład
Przewodnik: uzyskiwanie dostępu do sieci Web przy użyciu Async i Await (Visual Basic) Przedstawia, w jaki sposób konwertować synchroniczne rozwiązanie WPF do asynchronicznego rozwiązania WPF. Ta aplikacja pobiera szereg witryn sieci Web. Przykład asynchroniczny: programowanie asynchroniczne z funkcją Async i Await (Visual Basic)
Instrukcje: rozszerzanie przewodnika asynchronicznego przy użyciu funkcji Task.WhenAll (Visual Basic) Dodaje Task.WhenAll do poprzedniego przewodnika. Użycie polecenia WhenAll uruchamia wszystkie pliki do pobrania w tym samym czasie.
Instrukcje: równoległe tworzenie wielu żądań internetowych przy użyciu funkcji Async i Await (Visual Basic) Ilustruje, jak uruchomić kilka zadań w tym samym czasie. Przykład asynchroniczny: równoległe tworzenie wielu żądań internetowych
Asynchroniczne typy zwracane (Visual Basic) Ilustruje typy zwracane przez metody async i wyjaśnia, kiedy poszczególne typy są odpowiednie.
Kontrolowanie Flow w programach asynchronicznych (Visual Basic) Śledzi szczegółowo przepływ sterowania w serii wyrażeń await w programie asynchronicznym. Przykład asynchroniczny: sterowanie Flow w programach asynchronicznych
Dostrajanie aplikacji asynchronicznych (Visual Basic) Przedstawia, w jaki sposób dodać następujące funkcje do rozwiązania async:

- Anulowanie zadania asynchronicznego lub listy zadań (Visual Basic)
- Anulowanie zadań asynchronicznych po upływie czasu (Visual Basic)
- Anuluj pozostałe zadania asynchroniczne po zakończeniu jednego (Visual Basic)
- Uruchamianie wielu zadań asynchronicznych i przetwarzanie ich w miarę ich ukończenia (Visual Basic)
Przykład asynchroniczny: dostrajanie aplikacji
Obsługa ponownej obsługi w aplikacjach asynchronicznych (Visual Basic) Pokazuje, jak obsługiwać przypadki, w których aktywna operacja asynchroniczna jest uruchamiana ponownie podczas jej działania.
WhenAny: mostkowanie między .NET Framework a środowisko wykonawcze systemu Windows Pokazuje, jak połączyć typy zadań w .NET Framework i IAsyncOperations w środowisko wykonawcze systemu Windows, aby można było użyć metody WhenAny środowisko wykonawcze systemu Windows. Przykład asynchroniczny: mostkowanie między platformami .NET i środowisko wykonawcze systemu Windows (AsTask i WhenAny)
Anulowanie asynchroniczne: łączenie platformy .NET Framework ze środowiskiem wykonawczym systemu Windows Pokazuje, jak połączyć typy zadań w .NET Framework i IAsyncOperations w środowisko wykonawcze systemu Windows, aby można było użyć metody CancellationTokenSource środowisko wykonawcze systemu Windows. Przykład asynchroniczny: mostkowanie między platformą .NET i środowisko wykonawcze systemu Windows (anulowanie astask&)
Używanie asynchronicznego dostępu do plików (Visual Basic) Wyświetla listę korzyści wynikających ze stosowania słów kluczowych async i await przy uzyskiwaniu dostępu do plików.
Wzorzec asynchroniczny oparty na zadaniach (TAP) Opisano nowy wzorzec asynchronii w .NET Framework. Wzorzec jest oparty na typach Task i Task(Of TResult).
Asynchroniczne filmy wideo w witrynie Channel 9 Oferuje łącza do różnych plików wideo dotyczących programowania asynchronicznego.

Kompletny przykład

Poniższy kod to plik MainWindow.xaml.vb z aplikacji Windows Presentation Foundation (WPF), którą omówiono w tym temacie. Przykład można pobrać z przykładu asynchronicznego: przykład z sekcji "Programowanie asynchroniczne za pomocą Async i 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

Zobacz też