Asynchroniczne typy zwracane (Visual Basic)

Metody asynchroniczne mają trzy możliwe typy zwracane: Task<TResult>, Taski void. W języku Visual Basic zwracany typ void jest zapisywany jako procedura podrzędna. Aby uzyskać więcej informacji na temat metod asynchronicznych, zobacz Asynchroniczne programowanie za pomocą Async i Await (Visual Basic).

Każdy typ zwracany jest badany w jednej z poniższych sekcji i można znaleźć pełny przykład, który używa wszystkich trzech typów na końcu tematu.

Uwaga

Aby uruchomić przykład, na komputerze musi być zainstalowany program Visual Studio 2012 lub nowszy oraz program .NET Framework 4.5 lub nowszy.

Typ zwracany zadania (T)

Zwracany Task<TResult> typ jest używany dla metody asynchronicznej zawierającej instrukcję Return , w której operand ma typ TResult.

W poniższym przykładzie TaskOfT_MethodAsync metoda async zawiera instrukcję return zwracającą liczbę całkowitą. W związku z tym deklaracja metody musi określać typ zwracany .Task(Of Integer)

' TASK(OF T) EXAMPLE
Async Function TaskOfT_MethodAsync() As Task(Of Integer)

    ' The body of an async method is expected to contain an awaited
    ' asynchronous call.
    ' Task.FromResult is a placeholder for actual work that returns a string.
    Dim today As String = Await Task.FromResult(Of String)(DateTime.Now.DayOfWeek.ToString())

    ' The method then can process the result in some way.
    Dim leisureHours As Integer
    If today.First() = "S" Then
        leisureHours = 16
    Else
        leisureHours = 5
    End If

    ' Because the return statement specifies an operand of type Integer, the
    ' method must have a return type of Task(Of Integer).
    Return leisureHours
End Function

Gdy TaskOfT_MethodAsync jest wywoływana z wewnątrz wyrażenia await, wyrażenie await pobiera wartość całkowitą (wartość leisureHours) przechowywaną w zadaniu zwracanym przez TaskOfT_MethodAsyncelement . Aby uzyskać więcej informacji na temat wyrażeń await, zobacz Await Operator.

Następujące wywołania kodu i metoda awaits TaskOfT_MethodAsync. Wynik jest przypisywany do zmiennej result1 .

' Call and await the Task(Of T)-returning async method in the same statement.
Dim result1 As Integer = Await TaskOfT_MethodAsync()

Możesz lepiej zrozumieć, jak to się dzieje, oddzielając wywołanie TaskOfT_MethodAsync od aplikacji Await, jak pokazano w poniższym kodzie. Wywołanie metody TaskOfT_MethodAsync , która nie jest natychmiast oczekiwana, zwraca metodę Task(Of Integer), jak można oczekiwać od deklaracji metody. Zadanie jest przypisywane do zmiennej integerTask w przykładzie. Ponieważ integerTask jest elementem Task<TResult>, zawiera Result właściwość typu TResult. W tym przypadku funkcja TResult reprezentuje typ liczby całkowitej. Gdy Await jest stosowany do integerTaskelementu , wyrażenie await oblicza zawartość Result właściwości integerTask. Wartość jest przypisywana do zmiennej result2 .

Ostrzeżenie

Właściwość Result jest właściwością blokującą. Jeśli spróbujesz uzyskać dostęp do niego przed zakończeniem jego zadania, wątek, który jest obecnie aktywny, zostanie zablokowany do momentu zakończenia zadania i będzie dostępna wartość. W większości przypadków należy uzyskać dostęp do wartości przy użyciu metody Await zamiast bezpośrednio uzyskiwać dostęp do właściwości.

' Call and await in separate statements.
Dim integerTask As Task(Of Integer) = TaskOfT_MethodAsync()

' You can do other work that does not rely on resultTask before awaiting.
textBox1.Text &= "Application can continue working while the Task(Of T) runs. . . . " & vbCrLf

Dim result2 As Integer = Await integerTask

Instrukcje wyświetlania w poniższym kodzie sprawdzają, czy wartości result1 zmiennej, result2 zmiennej i Result właściwości są takie same. Należy pamiętać, że Result właściwość jest właściwością blokującą i nie powinna być dostępna przed oczekiwaniem na jego zadanie.

' Display the values of the result1 variable, the result2 variable, and
' the resultTask.Result property.
textBox1.Text &= vbCrLf & $"Value of result1 variable:   {result1}" & vbCrLf
textBox1.Text &= $"Value of result2 variable:   {result2}" & vbCrLf
textBox1.Text &= $"Value of resultTask.Result:  {integerTask.Result}" & vbCrLf

Typ zwracanego zadania

Metody asynchroniczne, które nie zawierają instrukcji return lub które zawierają instrukcję return, która nie zwraca operandu, zwykle ma typ Taskzwracany . Takie metody byłyby procedurami podrzędnych , gdyby zostały napisane w celu synchronicznego uruchamiania. Jeśli używasz typu zwracanego Task dla metody asynchronicznej, metoda wywołująca może użyć Await operatora do wstrzymania ukończenia obiektu wywołującego do momentu zakończenia wywoływanej metody asynchronicznej.

W poniższym przykładzie metoda Task_MethodAsync async nie zawiera instrukcji return. W związku z tym należy określić typ zwracany Task dla metody, która umożliwia oczekiwanie Task_MethodAsync . Definicja Task typu nie zawiera Result właściwości do przechowywania wartości zwracanej.

' TASK EXAMPLE
Async Function Task_MethodAsync() As Task

    ' The body of an async method is expected to contain an awaited
    ' asynchronous call.
    ' Task.Delay is a placeholder for actual work.
    Await Task.Delay(2000)
    textBox1.Text &= vbCrLf & "Sorry for the delay. . . ." & vbCrLf

    ' This method has no return statement, so its return type is Task.
End Function

Task_MethodAsync metoda jest wywoływana i oczekiwana przy użyciu instrukcji await zamiast wyrażenia await, podobnie jak instrukcja wywołująca dla metody synchronicznej Sub lub zwracanej przez void. Zastosowanie Await operatora w tym przypadku nie powoduje wygenerowania wartości.

Następujące wywołania kodu i metoda awaits Task_MethodAsync.

' Call and await the Task-returning async method in the same statement.
Await Task_MethodAsync()

Tak jak w poprzednim Task<TResult> przykładzie, można oddzielić wywołanie od Task_MethodAsync aplikacji Await operatora, jak pokazano w poniższym kodzie. Należy jednak pamiętać, że obiekt Task nie ma Result właściwości i że żadna wartość nie jest generowany, gdy operator await jest stosowany do obiektu Task.

Poniższy kod oddziela wywołanie Task_MethodAsync od oczekiwania na zwracane zadanie Task_MethodAsync .

' Call and await in separate statements.
Dim simpleTask As Task = Task_MethodAsync()

' You can do other work that does not rely on simpleTask before awaiting.
textBox1.Text &= vbCrLf & "Application can continue working while the Task runs. . . ." & vbCrLf

Await simpleTask

Typ powrotu void

Podstawowym zastosowaniem Sub procedur jest obsługa zdarzeń, gdzie nie ma zwracanego typu (nazywanego typem zwracanym void w innych językach). Zwracanie pustki może również służyć do zastępowania metod zwracania pustki lub metod, które wykonują działania, które można podzielić na "ogień i zapomnieć". Jednak należy zwrócić Task wszędzie tam, gdzie to możliwe, ponieważ nie można oczekiwać metody asynchronicznej zwracającej wartość void. Każdy obiekt wywołujący taką metodę musi być w stanie kontynuować uzupełnianie bez oczekiwania na zakończenie wywoływanej metody asynchronicznej, a obiekt wywołujący musi być niezależny od wszelkich wartości lub wyjątków generowanych przez metodę asynchroniową.

Obiekt wywołujący metody asynchronicznej nie może przechwytywać wyjątków zgłaszanych z metody, a takie nieobsługiwane wyjątki mogą spowodować niepowodzenie aplikacji. Jeśli wyjątek występuje w metodzie asynchronicznej, która zwraca wartość Task lub Task<TResult>, wyjątek jest przechowywany w zwracanym zadaniu i jest ponownie zwracany, gdy zadanie jest oczekiwane. W związku z tym upewnij się, że każda metoda asynchronizna, która może wygenerować wyjątek, ma zwracany typ Task lub Task<TResult> i że oczekuje się wywołań do metody.

Aby uzyskać więcej informacji na temat przechwytywania wyjątków w metodach asynchronicznych, zobacz Try... Złapać... Finally, instrukcja.

Poniższy kod definiuje asynchroniczny program obsługi zdarzeń.

' SUB EXAMPLE
Async Sub button1_Click(sender As Object, e As RoutedEventArgs) Handles button1.Click

    textBox1.Clear()

    ' Start the process and await its completion. DriverAsync is a
    ' Task-returning async method.
    Await DriverAsync()

    ' Say goodbye.
    textBox1.Text &= vbCrLf & "All done, exiting button-click event handler."
End Sub

Kompletny przykład

Poniższy projekt Windows Presentation Foundation (WPF) zawiera przykłady kodu z tego tematu.

Aby uruchomić projekt, wykonaj następujące kroki:

  1. Uruchom program Visual Studio.

  2. Na pasku menu wybierz pozycję Plik, Nowy, Projekt.

    Zostanie otwarte okno dialogowe Nowy projekt .

  3. W kategorii Zainstalowane szablony wybierz pozycję Visual Basic, a następnie wybierz pozycję Windows. Wybierz pozycję Aplikacja WPF z listy typów projektów.

  4. Wprowadź AsyncReturnTypes jako nazwę projektu, a następnie wybierz przycisk OK .

    Nowy projekt zostanie wyświetlony w Eksplorator rozwiązań.

  5. W edytorze programu Visual Studio Code wybierz kartę MainWindow.xaml .

    Jeśli karta nie jest widoczna, otwórz menu skrótów dla pliku MainWindow.xaml w Eksplorator rozwiązań, a następnie wybierz pozycję Otwórz.

  6. W oknie XAML pliku MainWindow.xaml zastąp kod poniższym kodem.

    <Window x:Class="MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            Title="MainWindow" Height="350" Width="525">
        <Grid>
            <Button x:Name="button1" Content="Start" HorizontalAlignment="Left" Margin="214,28,0,0" VerticalAlignment="Top" Width="75" HorizontalContentAlignment="Center" FontWeight="Bold" FontFamily="Aharoni" Click="button1_Click"/>
            <TextBox x:Name="textBox1" Margin="0,80,0,0" TextWrapping="Wrap" FontFamily="Lucida Console"/>
    
        </Grid>
    </Window>
    

    Proste okno zawierające pole tekstowe i przycisk pojawi się w oknie Projekt w pliku MainWindow.xaml.

  7. W Eksplorator rozwiązań otwórz menu skrótów dla MainWindow.xaml.vb, a następnie wybierz pozycję Wyświetl kod.

  8. Zastąp kod w MainWindow.xaml.vb następującym kodem.

    Class MainWindow
    
        ' SUB EXAMPLE
        Async Sub button1_Click(sender As Object, e As RoutedEventArgs) Handles button1.Click
    
            textBox1.Clear()
    
            ' Start the process and await its completion. DriverAsync is a
            ' Task-returning async method.
            Await DriverAsync()
    
            ' Say goodbye.
            textBox1.Text &= vbCrLf & "All done, exiting button-click event handler."
        End Sub
    
        Async Function DriverAsync() As Task
    
            ' Task(Of T)
            ' Call and await the Task(Of T)-returning async method in the same statement.
            Dim result1 As Integer = Await TaskOfT_MethodAsync()
    
            ' Call and await in separate statements.
            Dim integerTask As Task(Of Integer) = TaskOfT_MethodAsync()
    
            ' You can do other work that does not rely on resultTask before awaiting.
            textBox1.Text &= "Application can continue working while the Task(Of T) runs. . . . " & vbCrLf
    
            Dim result2 As Integer = Await integerTask
    
            ' Display the values of the result1 variable, the result2 variable, and
            ' the resultTask.Result property.
            textBox1.Text &= vbCrLf & $"Value of result1 variable:   {result1}" & vbCrLf
            textBox1.Text &= $"Value of result2 variable:   {result2}" & vbCrLf
            textBox1.Text &= $"Value of resultTask.Result:  {integerTask.Result}" & vbCrLf
    
            ' Task
            ' Call and await the Task-returning async method in the same statement.
            Await Task_MethodAsync()
    
            ' Call and await in separate statements.
            Dim simpleTask As Task = Task_MethodAsync()
    
            ' You can do other work that does not rely on simpleTask before awaiting.
            textBox1.Text &= vbCrLf & "Application can continue working while the Task runs. . . ." & vbCrLf
    
            Await simpleTask
        End Function
    
        ' TASK(OF T) EXAMPLE
        Async Function TaskOfT_MethodAsync() As Task(Of Integer)
    
            ' The body of an async method is expected to contain an awaited
            ' asynchronous call.
            ' Task.FromResult is a placeholder for actual work that returns a string.
            Dim today As String = Await Task.FromResult(Of String)(DateTime.Now.DayOfWeek.ToString())
    
            ' The method then can process the result in some way.
            Dim leisureHours As Integer
            If today.First() = "S" Then
                leisureHours = 16
            Else
                leisureHours = 5
            End If
    
            ' Because the return statement specifies an operand of type Integer, the
            ' method must have a return type of Task(Of Integer).
            Return leisureHours
        End Function
    
        ' TASK EXAMPLE
        Async Function Task_MethodAsync() As Task
    
            ' The body of an async method is expected to contain an awaited
            ' asynchronous call.
            ' Task.Delay is a placeholder for actual work.
            Await Task.Delay(2000)
            textBox1.Text &= vbCrLf & "Sorry for the delay. . . ." & vbCrLf
    
            ' This method has no return statement, so its return type is Task.
        End Function
    
    End Class
    
  9. Wybierz klawisz F5, aby uruchomić program, a następnie wybierz przycisk Uruchom .

    Powinny zostać wyświetlone następujące dane wyjściowe:

    Application can continue working while the Task<T> runs. . . .
    
    Value of result1 variable:   5
    Value of result2 variable:   5
    Value of integerTask.Result: 5
    
    Sorry for the delay. . . .
    
    Application can continue working while the Task runs. . . .
    
    Sorry for the delay. . . .
    
    All done, exiting button-click event handler.
    

Zobacz też