Udostępnij za pośrednictwem


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

Możesz uniknąć wąskich gardeł wydajności i zwiększyć ogólną szybkość reakcji aplikacji przy użyciu programowania asynchronicznego. Jednak tradycyjne techniki pisania aplikacji asynchronicznych mogą być skomplikowane, co utrudnia pisanie, debugowanie i konserwację.

Program Visual Studio 2012 wprowadził uproszczone podejście, programowanie asynchroniczne, które korzysta z asynchronicznej obsługi w programie .NET Framework 4.5 i nowszym, a także w środowisku uruchomieniowym systemu Windows. Kompilator wykonuje trudną pracę wykonaną przez dewelopera, a aplikacja zachowuje strukturę logiczną przypominającą kod synchroniczny. W rezultacie uzyskasz wszystkie zalety programowania asynchronicznego z ułamkiem nakładu pracy.

Ten temat zawiera omówienie czasu i sposobu używania programowania asynchronicznego oraz zawiera linki do tematów pomocy technicznej zawierających szczegóły i przykłady.

Asynchronizacja poprawia czas odpowiedzi

Asynchronia jest niezbędna w przypadku działań, które potencjalnie blokują, na przykład w przypadku uzyskiwania dostępu do internetu przez aplikację. Dostęp do zasobu internetowego czasami jest powolny lub opóźniony. Jeśli takie działanie jest blokowane w ramach procesu synchronicznego, cała aplikacja musi czekać. W procesie asynchronicznym aplikacja może kontynuować inną pracę, która nie zależy od zasobu internetowego, dopóki potencjalnie blokujące zadanie nie zostanie zakończone.

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

Obszar aplikacji Obsługa interfejsów API zawierających metody asynchroniczne
Dostęp do internetu HttpClient, SyndicationClient
Praca z plikami StorageFile, , StreamWriter, , StreamReaderXmlReader
Praca z obrazami MediaCapture, , BitmapEncoderBitmapDecoder
Programowanie WCF operacje synchroniczne i asynchroniczne

Asynchronia okazuje się szczególnie cenna w przypadku aplikacji, które uzyskują dostęp do wątku interfejsu użytkownika, ponieważ wszystkie operacje związane z interfejsem użytkownika zwykle dzielą jeden wątek. Jeśli jakikolwiek proces zostanie zablokowany w aplikacji synchronicznej, wszystkie zostaną zablokowane. Twoja aplikacja przestaje odpowiadać i możesz dojść do wniosku, że przestała działać, podczas gdy w rzeczywistości tylko czeka.

W przypadku używania metod asynchronicznych aplikacja nadal odpowiada na interfejs użytkownika. Możesz na przykład zmienić rozmiar lub zminimalizować okno albo zamknąć aplikację, jeśli nie chcesz czekać na jej zakończenie.

Podejście asynchroniczne dodaje odpowiednik automatycznej transmisji do listy opcji, które można wybrać podczas projektowania operacji asynchronicznych. Oznacza to, że uzyskujesz wszystkie korzyści z tradycyjnego programowania asynchronicznego, ale z znacznie mniejszym nakładem pracy od dewelopera.

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 programie .NET Framework lub środowisku uruchomieniowym systemu Windows, aby utworzyć metodę asynchroniczną niemal tak łatwo, jak tworzysz metodę synchroniczną. Metody asynchroniczne definiowane za pomocą metody Async i Await są określane jako metody asynchroniczne.

W poniższym przykładzie przedstawiono metodę asynchroniową. Prawie wszystko w kodzie powinno wyglądać zupełnie znajomo. Komentarze zwracają uwagę na funkcje, które dodajesz, aby stworzyć asynchronię.

Na końcu tego tematu można znaleźć kompletny przykładowy plik programu Windows Presentation Foundation (WPF), a ten można pobrać z Async Sample: Example from "Asynchronous Programming with Async and 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://learn.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 jego 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()

Oto charakterystyki, które sprawiają, że poprzedni przykład jest metodą asynchroniczną:

  • Podpis metody zawiera Async modyfikator.

  • Nazwa metody asynchronicznej zgodnie z konwencją kończy się sufiksem "Async".

  • Zwracany typ jest jednym z następujących typów:

    • Task(Of TResult), jeśli Twoja metoda zawiera instrukcję return, której operand jest typu 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 sekcję "Typy zwracane i parametry" w dalszej części tego tematu.

  • Metoda zwykle zawiera co najmniej jedno wyrażenie await, które oznacza punkt, w którym metoda nie może kontynuować, dopóki nie zostanie ukończona oczekiwana operacja asynchroniczna. W międzyczasie metoda jest zawieszona, a kontrolka powraca do elementu wywołującego metodę. W następnej sekcji tego tematu przedstawiono, co dzieje się w punkcie zawieszenia.

W metodach asynchronicznych używasz podanych słów kluczowych i typów, aby wskazać, co chcesz zrobić, a kompilator wykonuje resztę, w tym śledzenie tego, co musi się zdarzyć, gdy kontrolka powróci do punktu oczekiwania w zawieszonej metodzie. Niektóre rutynowe procesy, takie jak pętle i obsługa wyjątków, mogą być trudne do obsługi w tradycyjnym kodzie asynchronicznym. W metodzie asynchronicznej zapisujesz te elementy tak samo jak w rozwiązaniu synchronicznym, a problem zostanie rozwiązany.

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

Co się dzieje w metodzie Async

Najważniejszą rzeczą, jaką należy zrozumieć w programowaniu asynchronicznym, jest sposób, w jaki przepływ sterowania przechodzi z metody do metody. Na poniższym diagramie przedstawiono proces:

Diagram przedstawiający śledzenie programu asynchronicznego.

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

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

  2. AccessTheWebAsync tworzy instancję HttpClient, a następnie wywołuje asynchroniczną metodę GetStringAsync w celu pobrania zawartości witryny internetowej w postaci ciągu tekstowego.

  3. Coś dzieje się w GetStringAsync, co wstrzymuje jej postęp. Być może musi czekać na pobranie witryny 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 ciągły proces wywołania metody GetStringAsync, z zobowiązaniem do utworzenia rzeczywistej wartości ciągu po zakończeniu pracy.

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

  5. DoIndependentWork jest metodą synchroniczną, która wykonuje swoją pracę i wraca do wywołującego.

  6. AccessTheWebAsync skończyła się praca, którą można 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 ma ciągu.

    W związku z tym AccessTheWebAsync używa operatora await, aby zawiesić postęp i przekazać kontrolę metodzie, która wywołała AccessTheWebAsync. AccessTheWebAsync zwraca Task(Of Integer) do wywołującego. Zadanie reprezentuje obietnicę utworzenia wyniku całkowitego, który jest długością pobranego ciągu.

    Uwaga / Notatka

    Jeśli GetStringAsync (i dlatego getStringTask) zostanie ukończony zanim AccessTheWebAsync będzie na niego oczekiwać, kontrola pozostanie w AccessTheWebAsync. Koszt wstrzymania i następnie powrotu do AccessTheWebAsync zostałby zmarnowany, jeśli wywołany proces asynchroniczny (getStringTask) został już zakończony, a AccessTheWebSync nie musi czekać na ostateczny wynik.

    Wewnątrz elementu wywołującego (procedura obsługi zdarzeń w tym przykładzie) wzorzec przetwarzania jest kontynuowany. Wywołujący może wykonać inną pracę, która nie zależy od wyniku z AccessTheWebAsync, zanim zacznie na niego czekać, lub może czekać od razu. Procedura obsługi zdarzeń czeka na AccessTheWebAsyncelement i AccessTheWebAsync czeka na GetStringAsync.

  7. GetStringAsync kończy i generuje wynik tekstowy. Wynik ciągu nie jest zwracany przez wywołanie metody GetStringAsync w oczekiwany sposób. (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 elementu getStringTask. Instrukcja przypisania przypisuje pobrany wynik do urlContents.

  8. Gdy AccessTheWebAsync wynik ciągu, metoda może obliczyć długość ciągu. Następnie praca programu AccessTheWebAsync jest również zakończona, a program obsługi zdarzeń oczekiwania może wznawiać. W pełnym przykładzie na końcu tematu można potwierdzić, że program obsługi zdarzeń pobiera i wyświetla wartość wyniku długości.

Jeśli dopiero zaczynasz programować asynchroniczne, rozważ różnicę między zachowaniem synchronicznym i asynchronicznym. Metoda synchroniczna zwraca wartość po zakończeniu pracy (krok 5), ale metoda asynchroniczna zwraca wartość zadania, gdy praca jest zawieszona (kroki 3 i 6). Gdy metoda asynchronizna ostatecznie zakończy swoją pracę, zadanie zostanie oznaczone jako ukończone, a wynik , jeśli istnieje, jest przechowywany w zadaniu.

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

Asynchroniczne metody API

Być może zastanawiasz się, gdzie znaleźć metody takie jak GetStringAsync, które wspierają programowanie asynchroniczne. .NET Framework 4.5 lub nowszy zawiera wiele komponentów, które współpracują z Async i Await. Możesz rozpoznać te członki dzięki sufiksowi "Async", który jest dołączony do nazwy członka, oraz po zwracanym typie 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 uruchomieniowe systemu Windows zawiera również wiele metod, których można używać z Async i Await w aplikacjach systemu 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 środowiska uruchomieniowego systemu Windows) i WhenAny: mostkowanie między programem .NET Framework i środowiskiem uruchomieniowym systemu Windows.

Wątki

Metody asynchroniczne mają być operacjami nieblokacyjnymi. Wyrażenie Await w metodzie asynchronicznej nie blokuje bieżącego wątku, gdy oczekiwane zadanie jest uruchomione. Zamiast tego wyrażenie zarejestruje resztę metody jako kontynuację i zwraca kontrolkę do obiektu wywołującego metody asynchronicznej.

Słowa kluczowe Async i Await nie powodują tworzenia dodatkowych wątków. Metody asynchroniczne nie wymagają wielowątkowości, ponieważ metoda asynchroniczna nie działa na własnym wątku. Metoda jest uruchamiana w bieżącym kontekście synchronizacji i używa czasu w wątku tylko wtedy, gdy metoda jest aktywna. Możesz użyć Task.Run do przeniesienia prac CPU-zależnych do wątku w tle, ale wątek w tle nie pomaga w procesie, który po prostu czeka na dostępność wyników.

Podejście oparte na async do programowania asynchronicznego jest bardziej preferowane niż istniejące podejścia prawie w każdym przypadku. W szczególności takie podejście jest lepsze niż BackgroundWorker w przypadku operacji I/O, ponieważ kod jest prostszy i nie musisz chronić się przed warunkami wyścigu. W połączeniu z Task.Run, programowanie asynchroniczne jest lepsze niż BackgroundWorker w przypadku operacji ograniczonych przez procesor, ponieważ programowanie asynchroniczne oddziela szczegóły koordynacji uruchamiania kodu od pracy, którą Task.Run przenosi do puli wątków.

Async i Await

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

  • Oznaczona metoda asynchronizna może użyć funkcji Await do wyznaczenia punktów zawieszenia. Operator await informuje kompilator, że metoda asynchroniczna nie może przejść przez ten punkt do czasu ukończenia oczekiwanego procesu asynchronicznego. W międzyczasie kontrola powraca do obiektu wywołującego metodę async.

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

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

Metoda asynchroniczna zazwyczaj zawiera jedno lub więcej wystąpień operatora Await, ale brak wyrażeń Await nie prowadzi do 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żenie dotyczące takich metod.

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

Typy zwracane i parametry

W programowaniu platformy .NET Framework metoda asynchroniczna zwykle zwraca Task lub zadanie typu TResult. Wewnątrz metody asynchronicznej operator Await jest stosowany do zadania, które jest zwracane z wywołania innej metody asynchronicznej.

Jeżeli metoda zawiera instrukcję Return, która określa operand typu , powinieneś określić TResult jako typ zwracany.

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ą element 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 zwrócone zadanie reprezentuje bieżącą pracę. Zadanie zawiera informacje o stanie procesu asynchronicznego i ostatecznie obejmuje końcowy wynik procesu lub wyjątek zgłaszany przez proces, jeśli się nie powiedzie.

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

Metoda asynchroniczna, będąca Sub procedurą, nie może być oczekiwana, a obiekt wywołujący nie może przechwycić żadnych wyjątków zgłaszanych przez tę metodę.

Metoda asynchronizuj 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ładów, zobacz Async Return Types (Visual Basic). Aby uzyskać więcej informacji na temat przechwytywania wyjątków w metodach asynchronicznych, zobacz Try...Catch...Finally Statement.

Asynchroniczne interfejsy API w Windows Runtime mają jeden z następujących typów zwrotek, które są podobne do zadań.

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ę, w której zdarzenie, klasa bazowa lub kontrakt interfejsu sugeruje inną nazwę. Na przykład nie należy zmieniać nazw typowych programów obsługi zdarzeń, takich jak Button1_Click.

Tematy pokrewne i przykłady (Visual Studio)

Nazwa Opis Przykład
Przewodnik: uzyskiwanie dostępu do sieci Web przy użyciu Async i Await (Visual Basic) Pokazuje, jak przekonwertować synchroniczne rozwiązanie WPF na asynchroniczne rozwiązanie WPF. Aplikacja pobiera serię witryn internetowych. Przykład asynchroniczny: programowanie asynchroniczne z funkcją Async i Await (Visual Basic)
Porady: rozszerzanie przewodnika asynchronicznego przy użyciu elementu Task.WhenAll (Visual Basic) Dodaje Task.WhenAll do poprzedniego przewodnika. Użycie polecenia WhenAll uruchamia jednocześnie wszystkie pobrane pliki.
Porady: równoległe tworzenie wielu żądań internetowych przy użyciu Async i Await (Visual Basic) Demonstruje sposób uruchamiania kilku zadań w tym samym czasie. Przykład asynchroniczny: równoległe tworzenie wielu żądań internetowych
Asynchroniczne typy zwracane (Visual Basic) Ilustruje typy, które metody asynchroniczne mogą zwracać i wyjaśniać, kiedy każdy typ jest odpowiedni.
Przepływ sterowania w programach asynchronicznych (Visual Basic) Szczegółowo śledzi przebieg sterowania przez ciąg wyrażeń await w programie asynchronicznym. Przykład asynchroniczny: przepływ sterowania w programach asynchronicznych
Fine-Tuning Twoja aplikacja asynchroniczna (Visual Basic) Pokazuje, jak dodać następujące funkcje do rozwiązania asynchronicznego:

- Anulowanie zadania asynchronicznego lub listy zadań (Visual Basic)
- Anulowanie zadań asynchronicznych po upływie czasu (Visual Basic)
- Anulowanie pozostałych zadań asynchronicznych po zakończeniu jednego (Visual Basic)
- Uruchamianie wielu zadań asynchronicznych i przetwarzanie ich podczas ich wykonywania (Visual Basic)
Przykład asynchroniczny: dostrajanie aplikacji
Obsługa ponownego uwierzytelniania w aplikacjach asynchronicznych (Visual Basic) Pokazuje, jak obsługiwać przypadki, w których aktywna operacja asynchroniczna jest ponownie uruchamiana podczas jej działania.
WhenAny: łączenie między .NET Framework a Windows Runtime Pokazuje, jak połączyć typy zadań w programie .NET Framework i IAsyncOperations w środowisku uruchomieniowym systemu Windows, aby można było używać z WhenAny metodą środowiska uruchomieniowego systemu Windows. Przykład asynchroniczny: mostkowanie między platformą .NET i środowiskiem uruchomieniowym systemu Windows (AsTask i WhenAny)
Anulowanie asynchroniczne: mostkowanie między programem .NET Framework i środowiskiem uruchomieniowym systemu Windows Pokazuje, jak połączyć typy zadań w programie .NET Framework i IAsyncOperations w środowisku uruchomieniowym systemu Windows, aby można było używać z CancellationTokenSource metodą środowiska uruchomieniowego systemu Windows. Przykład asynchroniczny: mostkowanie między platformą .NET i środowiskiem uruchomieniowym systemu Windows (AsTask i anulowanie)
Używanie asynchronicznego dostępu do plików (Visual Basic) Wyświetla listę i demonstruje zalety użycia async i await do dostępu do plików.
Wzorzec asynchroniczny oparty na zadaniach (TAP) Opisuje nowy wzorzec asynchronii w programie .NET Framework. Wzorzec jest oparty na typach Task i Task(Of TResult).

Kompletny przykład

Poniższy kod to plik MainWindow.xaml.vb z aplikacji Windows Presentation Foundation (WPF), którą omawia ten temat. Można pobrać przykład z Async Sample: Example from "Asynchronous Programming with Async and Await".


Imports System.Net.Http

' Example that demonstrates Asynchronous Programming 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://learn.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 także