Asynchroniczne typy zwracane (Visual Basic)

Metody asynchroniczne mają trzy możliwe typy zwracane: Task<TResult> Task , i void. W Visual Basic zwracany typ void jest zapisywany jako procedura Sub. Aby uzyskać więcej informacji na temat metod asynchronicznych, zobacz Programowanie asynchroniczne z Async i Await (Visual Basic).

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

Uwaga

Aby uruchomić przykład, musisz mieć zainstalowany program Visual Studio 2012 lub nowszą oraz .NET Framework 4.5 lub nowszą.

Zwracany typ task(T)

Zwracany typ jest używany dla metody asynchronicznej, która zawiera instrukcje Return, w której Task<TResult> operand ma typ TResult .

W poniższym przykładzie metoda TaskOfT_MethodAsync async zawiera instrukcje return, które zwracają liczbę całkowitą. W związku z tym deklaracja metody musi określać zwracany typ 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 element jest wywoływany z poziomu wyrażenia await, wyrażenie await pobiera wartość całkowitą (wartość ) przechowywaną w zadaniu zwróconym przez element TaskOfT_MethodAsync leisureHours TaskOfT_MethodAsync . Aby uzyskać więcej informacji na temat wyrażeń await, zobacz Await Operator.

Poniższy kod wywołuje metodę i awaits TaskOfT_MethodAsync . Wynik jest przypisywany do result1 zmiennej .

' 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 od TaskOfT_MethodAsync aplikacji Await , jak pokazano w poniższym kodzie. Wywołanie metody, która nie jest od razu oczekiwana, zwraca wartość , jak można oczekiwać od deklaracji TaskOfT_MethodAsync Task(Of Integer) metody . Zadanie jest przypisane do zmiennej integerTask w przykładzie. Ponieważ integerTask obiekt jest Task<TResult> obiektem , zawiera właściwość typu Result TResult . W tym przypadku TResult reprezentuje typ liczby całkowitej. Po zastosowaniu do obiektu wyrażenie await oblicza zawartość Await integerTask właściwości Result integerTask . Wartość jest przypisywana do result2 zmiennej .

Ostrzeżenie

Właściwość Result jest właściwością blokującą. Jeśli spróbujesz uzyskać do niego dostęp przed zakończeniem zadania, wątek, który jest obecnie aktywny, zostanie zablokowany do momentu ukończenia zadania i uzyskania dostępnej wartości. W większości przypadków należy uzyskać dostęp do wartości przy użyciu zamiast bezpośrednio Await uzyskać 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 display w poniższym kodzie sprawdzają, czy wartości zmiennej, zmiennej i result1 result2 właściwości są takie Result same. Pamiętaj, że właściwość jest właściwością blokującą i nie powinna być dostępna Result przed oczekiwaniem na jej 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

Zwracany typ zadania

Metody asynchroniczne, które nie zawierają instrukcji return lub zawierają instrukcje return, które nie zwracają operandu, zwykle mają zwracany typ Task . Takie metody to procedury podrzędne, jeśli zostały napisane do uruchamiania synchronicznego. Jeśli używasz zwracanych typów dla metody asynchronicznej, metoda wywołująca może użyć operatora , aby wstrzymać uzupełnianie obiektu wywołującego do momentu zakończenia wywoływanej metody Task Await asynchronicznej.

W poniższym przykładzie metoda asynchroniczna Task_MethodAsync nie zawiera instrukcji return. W związku z tym należy określić zwracany typ Task dla metody , co umożliwia Task_MethodAsync oczekiwanie. Definicja typu nie zawiera właściwości do Task Result 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 w przypadku instrukcji wywołującej dla metody synchronicznej Sub lub zwracanej metodą void. Zastosowanie operatora Await w tym przypadku nie spowoduje uzyskania wartości.

Poniższy kod wywołuje metodę i awaits Task_MethodAsync .

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

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

Poniższy kod oddziela wywołanie od Task_MethodAsync oczekiwania na zadanie, które Task_MethodAsync zwraca.

' 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

Zwracany typ Void

Podstawowym zastosowaniem procedur są procedury obsługi zdarzeń, w których nie ma typu zwracanego (w innych językach jest określany jako Sub typ zwracany void). Zwracany w sposób nieważny może być również używany do zastępowania metod zwracających void lub metod, które wykonują działania, które można sklasyfikować jako "wyzpal i zapomnij". Należy jednak zwracać metodę wszędzie tam, gdzie to możliwe, ponieważ nie można czekać na metodę asynchroniczną zwracaną przez Task void. Każdy wywołujący taką metodę musi być w stanie kontynuować uzupełnianie bez oczekiwania na zakończenie wywoływanej metody asynchronicznej, a wywołujący musi być niezależny od wszelkich wartości lub wyjątków generowanych przez metodę asynchroniczną.

Wywołujący metodę asynchroniczną zwracaną przez void nie może przechwycić wyjątków zgłaszanych przez metodę, a takie nieobsługiwane wyjątki mogą spowodować niepowodzenie aplikacji. Jeśli w metodzie asynchronicznej wystąpi wyjątek, który zwraca wartość lub , wyjątek jest przechowywany w zwróconym zadaniu i ponownie występuje, gdy zadanie Task Task<TResult> jest oczekujące. W związku z tym upewnij się, że każda metoda asynchroniczna, która może tworzyć wyjątek, ma zwracany typ lub i oczekuje na wywołania Task Task<TResult> metody .

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

Poniższy kod definiuje asynchroniczną obsługę 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, Project.

    Zostanie otwarte Project nowe okno dialogowe.

  3. W kategorii Zainstalowane szablony wybierz pozycję Visual Basic, a następnie wybierz 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 Visual Studio Code wybierz kartę MainWindow.xaml.

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

  6. W oknie XAML pliku MainWindow.xaml zastąp kod następującym 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>
    

    W oknie Projekt pliku MainWindow.xaml zostanie wyświetlone proste okno zawierające pole tekstowe i przycisk.

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

  8. Zastąp kod w pliku 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ż