Udostępnij za pośrednictwem


Asynchroniczne typy zwracane (C# i Visual Basic)

Metody asynchroniczne mają trzy możliwe zwracane typy: Task, Task, oraz typ void.W języku Visual Basic, zwrócony typ void jest napisany w postaci Sub procedury.Aby uzyskać więcej informacji na temat metod asynchronicznych, zobacz Programowanie asynchroniczne z Async i Await (C# i Visual Basic).

Każdy typ zwracany jest badany w jednej z następujących sekcji. Na końcu tematu można znaleźć pełny przykład, który używa wszystkich trzech typów.

[!UWAGA]

Aby uruchomić przykład, na komputerze musisz mieć zainstalowane programy Visual Studio 2012, Visual Studio 2013, Visual Studio Express 2012 for Windows Desktop, Visual Studio Express 2013 for Windows lub .NET Framework w wersji 4.5 lub 4.5.1.

Ten temat zawiera następujące sekcje.

  • Zwracany typ Task(T)
  • Zwracany typ Task
  • Typ zwracany Void
  • Kompletny przykład
  • Tematy pokrewne

Zwracany typ Task(T)

Typ zwracany Task jest stosowany w metodzie asynchronicznej, która zawiera instrukcję Return (Visual Basic) lub return (C#), w której operator ma typ TResult.

W poniższym przykładzie TaskOfT_MethodAsync metoda asynchronicza zawiera instrukcję return, która zwraca liczbę całkowitą.Dlatego deklaracja metody musi określać typ zwracany Task(Of Integer) w języku Visual Basic lub Task<int> w języku C#.

' 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<T> EXAMPLE
async Task<int> TaskOfT_MethodAsync()
{
    // The body of the method is expected to contain an awaited asynchronous 
    // call. 
    // Task.FromResult is a placeholder for actual work that returns a string. 
    var today = await Task.FromResult<string>(DateTime.Now.DayOfWeek.ToString());

    // The method then can process the result in some way. 
    int leisureHours;
    if (today.First() == 'S')
        leisureHours = 16;
    else
        leisureHours = 5;

    // Because the return statement specifies an operand of type int, the 
    // method must have a return type of Task<int>. 
    return leisureHours;
}

Gdy TaskOfT_MethodAsync jest wywoływane z poziomu wyrażenia await, wyrażenie await pobiera wartość całkowitą (wartość leisureHours), która jest przechowywana w zadaniu zwracanym przez TaskOfT_MethodAsync.Aby uzyskać więcej informacji dotyczących wyrażeń oczekiwania, zobacz Await — Operator (Visual Basic) lub await (odwołanie w C#).

Poniższy kod wywołuje i czeka na metodę TaskOfT_MethodAsync.Wynik jest przypisany do zmiennej result1.

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

Można lepiej zrozumieć, jak to się dzieje oddzielając wywołanie TaskOfT_MethodAsync od stosowania Await lub await, jak przedstawiono na przykładzie poniższego kodu.Wywołanie metody TaskOfT_MethodAsync , która nie jest oczekiwana natychmiast zwraca Task(Of Integer) lub Task<int>, jak można się spodziewać po deklaracji metody.Zadanie zostanie przypisane do zmiennej integerTask w tym przykładzie.Ponieważ integerTask jest Task, zawiera właściwość Result typu TResult.W tym przypadku TResult reprezentuje typ liczby całkowitej.Gdy Await lub await jest stosowane do integerTask, wyrażenie czekania zwraca wynik we właściwości Result typu integerTask.Wartość jest przypisana do zmiennej result2.

Informacje dotyczące przestrogiPrzestroga

Właściwość Result jest właściwością blokowania.Jeśli próbujesz uzyskać do niej dostęp przed zakończeniem jej zadania, wątek, który jest obecnie aktywny, jest zablokowany, dopóki zadanie nie zakończy się, a wartość jest dostępna.W większości przypadków dostęp do wartości powinien być uzyskany za pomocą operatora Await lub 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 &= String.Format("Application can continue working while the Task(Of T) runs. . . . " & vbCrLf)

Dim result2 As Integer = Await integerTask
// Call and await in separate statements.
Task<int> integerTask = TaskOfT_MethodAsync();

// You can do other work that does not rely on integerTask before awaiting.
textBox1.Text += String.Format("Application can continue working while the Task<T> runs. . . . \r\n");

int result2 = await integerTask;

Instrukcje wyświetlania w poniższym kodzie sprawdzają, czy wartości zmiennej result1, zmiennej result2 i właściwości Result nie są takie same.Należy pamiętać, że Result właściwość jest właściwością blokowania i nie powinna być dostępna zanim jej zadanie nie było oczekiwane.

' Display the values of the result1 variable, the result2 variable, and 
' the resultTask.Result property.
textBox1.Text &= String.Format(vbCrLf & "Value of result1 variable:   {0}" & vbCrLf, result1)
textBox1.Text &= String.Format("Value of result2 variable:   {0}" & vbCrLf, result2)
textBox1.Text &= String.Format("Value of resultTask.Result:  {0}" & vbCrLf, integerTask.Result)
// Display the values of the result1 variable, the result2 variable, and 
// the integerTask.Result property.
textBox1.Text += String.Format("\r\nValue of result1 variable:   {0}\r\n", result1);
textBox1.Text += String.Format("Value of result2 variable:   {0}\r\n", result2);
textBox1.Text += String.Format("Value of integerTask.Result: {0}\r\n", integerTask.Result);

Zwracany typ Task

Metody asynchroniczne, które nie zawierają instrukcji return lub zawierają instrukcję return, która nie zwraca operandu są zazwyczaj metodami typu Task.Takie metody byłyby metodami zwracającymi wartość pustą (procedury Sub w języku Visual Basic), jeśli zostałyby napisane tak, aby były uruchamiane synchronicznie.Jeśli używasz typu zwracanego Task dla metody asynchronicznej, metoda wywołująca może użyć operatora await do zawieszenia wykonania obiektu wywołującego aż do zakończenia wywołanej metody asynchronicznej.

W poniższym przykładzie, metoda async Task_MethodAsync nie zawiera instrukcji return.Dlatego należy określić typ zwracany Task dla metody, która umożliwia oczekiwanie na metodę Task_MethodAsync.Definicja typu Task nie zawiera właściwości Result służącej 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 &= String.Format(vbCrLf & "Sorry for the delay. . . ." & vbCrLf)

    ' This method has no return statement, so its return type is Task.  
End Function
// TASK EXAMPLE
async Task Task_MethodAsync()
{
    // 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);
    // Task.Delay delays the following line by two seconds.
    textBox1.Text += String.Format("\r\nSorry for the delay. . . .\r\n");

    // This method has no return statement, so its return type is Task.  
}

Metoda Task_MethodAsync jest wywoływana i ustawiana jako oczekiwana za pomocą instrukcji await, a nie wyrażenia await, co przypomina wywoływanie synchronicznej procedury Sub lub metody zwracającej wartość pustą.W tym przypadku zastosowanie operatora await nie generuje wartości.

Poniższy kod wywołuje i czeka na metody Task_MethodAsync.

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

Jak w poprzednim przykładzie Task, możesz oddzielić wywołanie Task_MethodAsync z aplikacji operatora await, jak to ukazuje poniższy kod.Jednak należy pamiętać, że element Task nie ma właściwości Result i że wartość nie jest generowana, gdy operator await jest stosowany do elementu Task.

Poniższy kod oddziela wywoływanie metody Task_MethodAsync od oczekiwania na zadanie, które zwraca metoda 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 &= String.Format(vbCrLf & "Application can continue working while the Task runs. . . ." & vbCrLf)

Await simpleTask
// Call and await in separate statements.
Task simpleTask = Task_MethodAsync();

// You can do other work that does not rely on simpleTask before awaiting.
textBox1.Text += String.Format("\r\nApplication can continue working while the Task runs. . . .\r\n");

await simpleTask;

Typ zwracany Void

Podstawowym zastosowaniem typu zwracanego void (procedury Sub w języku Visual Basic) są procedury obsługi zdarzeń, w których typ zwracany void jest wymagany.Zwracany typ void może również służyć do nadpisywania metod zwracających wartość void lub dla metod, które wykonują czynności, które można skategoryzować jako "fire and forget." Należy jednak zwrócić Task wszędzie tam, gdzie to możliwe, ponieważ metoda async zwraca void nie oczekiwany.Dowolny obiekt wywołujący taką metodę musi być w stanie kontynuować do zakończenia bez oczekiwania na zakończenie wywołanej metody asynchronicznej, a obiekt wywołujący musi być niezależny od wartości lub wyjątków, które generuje metoda asynchroniczna.

Obiekt wywołujący metodę asynchroniczną zwracającą wartość pustą nie może przechwytywać wyjątków, które są generowane przez tę metodę, i takie nieobsłużone wyjątki mogą spowodować awarię aplikacji.Jeśli wystąpi wyjątek w metodzie asynchronicznej, która zwraca atrybut Task lub Task, wyjątek jest przechowywany w zwróconym zadaniu i ponownie zgłaszany, gdy zadanie jest oczekiwane.Dlatego upewnij się, że każda metoda asynchroniczna, która może spowodować wyjątek, ma typ zwracany Task lub Task i że trwa oczekiwanie na wywołanie metody.

Aby uzyskać więcej informacji dotyczących wyjątków catch w metodach asynchronicznych, zobacz try-catch (odwołanie w C#) lub Try...Catch...Finally — Instrukcja (Visual Basic).

Poniższy kod definiuje obsługę zdarzeń asynchronicznych.

' 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
// VOID EXAMPLE 
private async void button1_Click(object sender, RoutedEventArgs e)
{
    textBox1.Clear();

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

    // Say goodbye.
    textBox1.Text += "\r\nAll done, exiting button-click event handler.";
}

Kompletny przykład

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

Aby uruchomić projekt, należy wykonać następujące czynności:

  1. Uruchom program Visual Studio.

  2. W pasku menu wybierz Plik, Nowy, Projekt.

    Zostanie otwarte okno dialogowe Nowy projekt.

  3. W kategorii Zainstalowane, Szablony wybierz Visual Basic lub Visual C#, a następnie wybierz polecenie Windows.Z listy typów projektów wybierz Pusta aplikacja (WPF).

  4. Wprowadź AsyncReturnTypes jako nazwę projektu, a następnie naciśnij przycisk OK.

    W Eksploratorze rozwiązań pojawi się nowy projekt.

  5. W Edytorze koloru programu Visual Studio wybierz kartę MainWindow.xaml.

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

  6. W oknie XAML pliku MainWindow.xaml, zastąp kod następującym kodem.

    <Window x:Class="MainWindow"
            xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="https://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>
    
    <Window x:Class="AsyncReturnTypes.MainWindow"
            xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="https://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 pojawia się w oknie Projekt MainWindow.xaml.

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

  8. Zastąp kod w MainWindow.xaml.vb lub MainWindow.xaml.cs 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 &= String.Format("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 &= String.Format(vbCrLf & "Value of result1 variable:   {0}" & vbCrLf, result1)
            textBox1.Text &= String.Format("Value of result2 variable:   {0}" & vbCrLf, result2)
            textBox1.Text &= String.Format("Value of resultTask.Result:  {0}" & vbCrLf, integerTask.Result)
    
            ' 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 &= String.Format(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 &= String.Format(vbCrLf & "Sorry for the delay. . . ." & vbCrLf)
    
            ' This method has no return statement, so its return type is Task.  
        End Function 
    
    End Class
    
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Data;
    using System.Windows.Documents;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Imaging;
    using System.Windows.Navigation;
    using System.Windows.Shapes;
    
    namespace AsyncReturnTypes
    {
        public partial class MainWindow : Window
        {
            public MainWindow()
            {
                InitializeComponent();
            }
    
            // VOID EXAMPLE 
            private async void button1_Click(object sender, RoutedEventArgs e)
            {
                textBox1.Clear();
    
                // Start the process and await its completion. DriverAsync is a  
                // Task-returning async method.
                await DriverAsync();
    
                // Say goodbye.
                textBox1.Text += "\r\nAll done, exiting button-click event handler.";
            }
    
            async Task DriverAsync()
            {
                // Task<T>  
                // Call and await the Task<T>-returning async method in the same statement. 
                int result1 = await TaskOfT_MethodAsync();
    
                // Call and await in separate statements.
                Task<int> integerTask = TaskOfT_MethodAsync();
    
                // You can do other work that does not rely on integerTask before awaiting.
                textBox1.Text += String.Format("Application can continue working while the Task<T> runs. . . . \r\n");
    
                int result2 = await integerTask;
    
                // Display the values of the result1 variable, the result2 variable, and 
                // the integerTask.Result property.
                textBox1.Text += String.Format("\r\nValue of result1 variable:   {0}\r\n", result1);
                textBox1.Text += String.Format("Value of result2 variable:   {0}\r\n", result2);
                textBox1.Text += String.Format("Value of integerTask.Result: {0}\r\n", integerTask.Result);
    
                // Task 
                // Call and await the Task-returning async method in the same statement.
                await Task_MethodAsync();
    
                // Call and await in separate statements.
                Task simpleTask = Task_MethodAsync();
    
                // You can do other work that does not rely on simpleTask before awaiting.
                textBox1.Text += String.Format("\r\nApplication can continue working while the Task runs. . . .\r\n");
    
                await simpleTask;
            }
    
            // TASK<T> EXAMPLE
            async Task<int> TaskOfT_MethodAsync()
            {
                // The body of the method is expected to contain an awaited asynchronous 
                // call. 
                // Task.FromResult is a placeholder for actual work that returns a string. 
                var today = await Task.FromResult<string>(DateTime.Now.DayOfWeek.ToString());
    
                // The method then can process the result in some way. 
                int leisureHours;
                if (today.First() == 'S')
                    leisureHours = 16;
                else
                    leisureHours = 5;
    
                // Because the return statement specifies an operand of type int, the 
                // method must have a return type of Task<int>. 
                return leisureHours;
            }
    
    
            // TASK EXAMPLE
            async Task Task_MethodAsync()
            {
                // 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);
                // Task.Delay delays the following line by two seconds.
                textBox1.Text += String.Format("\r\nSorry for the delay. . . .\r\n");
    
                // This method has no return statement, so its return type is Task.  
            }
        }
    }
    
  9. Wybierz klawisz F5, aby uruchomić program, a następnie wybierz przycisk Start.

    Powinny zostać wyświetlone poniższe 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ż

Zadania

Wskazówki: uzyskiwanie dostępu do sieci za pomocą Async i Await (C# i Visual Basic)

Wskazówki: Korzystanie z debugera i metod asynchronicznych

Informacje

async (odwołanie w C#)

Async (Visual Basic)

Await — Operator (Visual Basic)

await (odwołanie w C#)

FromResult``1

Koncepcje

Przepływ sterowania w aplikacjach asynchronicznych (C# i Visual Basic)