Sdílet prostřednictvím


Asynchronní návratové typy (C# and Visual Basic)

Asynchronní metody mají tři možné návratové typy: Task, Task a void.V jazyce Visual Basic je návratový typ void napsán jako dílčí procedura.Další informace o metodách async naleznete v tématu Asynchronní programování pomocí modifikátoru Async a operátoru Await (C# a Visual Basic).

Každý návratový typ je zkontrolován v jedné z následujících částí a na konci tématu naleznete kompletní příklad, který používá všechny tři typy.

[!POZNÁMKA]

Chcete-li spustit příklad, musíte mít nainstalovanou aplikaci Visual Studio 2012, Visual Studio 2013, Visual Studio Express 2012 for Windows Desktop, Visual Studio Express 2013 for Windows nebo rozhraní .NET Framework 4.5 nebo 4.5.1 v počítači.

Toto téma obsahuje následující oddíly.

  • Návratový typ Task(T)
  • Návratový typ úlohy
  • Návratový typ void
  • Kompletní příklad
  • Příbuzná témata

Návratový typ Task(T)

Návratový typ Task se používá pro asynchronní metodu obsahující příkaz Return (Visual Basic) nebo return (C#), který určuje typ operandu TResult.

V následujícím příkladu asynchronní metoda TaskOfT_MethodAsync obsahuje příkaz return, který vrátí celé číslo.Deklarace metody musí proto určit návratový typ Task(Of Integer) v jazyce Visual Basic nebo Task<int> v jazyce 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;
}

Při volání TaskOfT_MethodAsync z výrazu await výraz await získá celočíselnou hodnota (hodnotu leisureHours), která je uložena v úkolu, který je vrácen vlastností TaskOfT_MethodAsync.Další informace o výrazech await naleznete v tématu Await – operátor (Visual Basic) nebo await – – operátor (Referenční dokumentace jazyka C#).

Následující kód volá a čeká metodu TaskOfT_MethodAsync.Výsledek je přiřazen do proměnné 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();

Postupu lépe porozumíte oddělením volání do TaskOfT_MethodAsync od aplikace Await nebo await, jak ukazuje následující kód.Volání metody TaskOfT_MethodAsync, které není okamžitě očekáváno, vrátí Task(Of Integer) nebo Task<int>, dle očekávání od deklarace metody.Úkol je přidělen proměnné integerTask v příkladu.Protože integerTask je Task, obsahuje vlastnostResult typu TResult.V tomto případě TResult představuje typ integer.Když se Await nebo await aplikuje na integerTask, výraz await se vyhodnocuje na obsah vlastnosti Result výrazu integerTask.Hodnota přiřazená k proměnné result2.

Poznámka k upozorněníUpozornění

Vlastnost Result je vlastnost blokování.Pokud se pokusíte o přístup k ní před dokončením její úlohy, právě aktivní vlákno bude blokováno, dokud úloha nebude dokončena a hodnota nebude k dispozici.Ve většině případů byste měli přistupovat k hodnotě pomocí metod Await nebo await namísto přímého přístupu.

' 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;

Zobrazení příkazů v následujícím kódu ověří, že hodnoty proměnné result1, result2 a vlastnost Result jsou stejné.Mějte na paměti, že vlastnost Result je vlastnost blokování a neměli byste k ní přistupovat před očekáváním jejího úkolu.

' 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);

Návratový typ úlohy

Asynchronní metody, které neobsahují příkaz return nebo obsahující příkaz return, který nevrací operand, obvykle mají návratový typ Task.Tyto metody by měly zamezit vrácení metod (procedury Sub v jazyce Visual Basic), pokud byly napsány, aby běžely synchronně.Používáte-li návratový typ Task pro asynchronní metodu, volající metoda můžete použít operátor await k pozastavení dokončení volajícího až do dokončení volané asynchronní metody.

V následujícím příkladu asynchronní metoda Task_MethodAsync neobsahuje příkaz return.Tedy zadáte návratový typ Task pro metodu, která umožňuje očekávání Task_MethodAsync.Definice Task neobsahuje vlastnost Result k ukládání vrácené hodnoty.

' 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.  
}

Task_MethodAsync je volán a očekáván pomocí příkazu await namísto výrazu await, podobného volání příkazu pro synchronní Sub nebo metodu vracející hodnotu void.V tomto případě aplikace operátoru await nevytvoří hodnotu.

Následující kód volá a čeká metodu 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();

Stejně jako v předchozím příkladu Task můžete oddělit volání Task_MethodAsync od použití operátoru await, jak ukazuje následující kód.Nezapomeňte však, že Task nemá vlastnost Result, a že se nevytvoří žádná hodnota, pokud použijete operátor „await“ v rámci Task.

Následující kód oddělí volání Task_MethodAsync z čekajícího na úkol, který vrátí 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;

Návratový typ void

Primární použití typu vrácené hodnoty void (procedury Sub v jazyce Visual Basic) je v obslužné rutině události, kde je požadován typ vrácené hodnoty void.Vrácení void lze také použít k přepsání metod vracejících void nebo pro metody, které vykonávají činnosti, které lze označit jako "vypal a zapomeň". Měli byste však vrátit hodnotu Task vždy, kdy je to možné, protože nelže očekávat asynchronní metody vracející hodnotu void.Jakýkoli volající této metody musí být schopen pokračovat v dokončení bez čekání na dokončení volané asynchronní metody a volající musí být nezávislý na všech hodnotách nebo výjimkách, které generuje asynchronní metoda.

Volání asynchronní metody vracející void nemůže zachytit výjimky, které jsou vyvolány z metody a takové neošetřené výjimky mohou způsobit selhání aplikace.Pokud dojde k výjimce v asynchronní metodě, která vrací Task nebo Task, výjimka se uloží v rámci vrácené úlohy a je znovu vyvolána při očekávání úkolu.Proto se ujistěte, že asynchronní metody, které mohou způsobit výjimku, mají návratový typ Task nebo Task a že tato volání metody jsou očekávaná.

Další informace o tom, jak zachytávat výjimky v asynchronních metodách, naleznete v tématu try-catch (Referenční dokumentace jazyka C#) nebo Try...Catch....Finally – příkaz (Visual Basic).

Následující kód definuje asynchronní obslužnou rutinu.

' 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.";
}

Kompletní příklad

Následující projekt Windows Presentation Foundation (WPF) obsahuje příklady kódů z tohoto tématu.

Chcete-li spustit projekt, proveďte následující kroky:

  1. Spusťte aplikaci Visual Studio.

  2. Na panelu nabídky vyberte možnosti Soubor, Nový, Projekt.

    Otevře se dialogové okno Nový projekt.

  3. V kategorii Nainstalováno, Šablony zvolte možnost Visual Basic nebo Visual C# a pak zvolte možnost Windows.V seznamu typů projektů klepněte na příkaz Aplikace WPF.

  4. Zadejte AsyncReturnTypes jako název projektu a klikněte na tlačítko OK.

    V podokně Průzkumník řešení se zobrazí nový projekt.

  5. V editoru kódu sady Visual Studio zvolte kartu MainWindow.xaml.

    Pokud karta není zobrazena, otevřete místní nabídku souboru MainWindow.xaml v Průzkumníkovi řešení a vyberte možnost Otevřít.

  6. V okně XAML pro soubor MainWindow.xaml nahraďte kód následujícím kódem.

    <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>
    

    Jednoduché okno obsahující textové pole a tlačítko se zobrazí v okně Návrh souboru MainWindow.xaml.

  7. V Průzkumníku řešení otevřete místní nabídku pro soubor MainWindow.xaml.vb nebo MainWindow.xaml.cs a pak zvolte možnost Zobrazit kód.

  8. Nahraďte kód v souborech MainWindow.xaml.vb nebo MainWindow.xaml.cs následujícím kódem.

    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. Zvolte klávesu F5 ke spuštění programu a pak zvolte tlačítko Start.

    Měl by se zobrazit následující výstup.

    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.
    

Viz také

Úkoly

Návod: Přístup k webu pomocí modifikátoru Async a operátoru Await (C# a Visual Basic)

Postupy: Použití ladicího programu u asynchronních metod

Referenční dokumentace

async (Referenční dokumentace jazyka C#)

Async (Visual Basic)

Await – operátor (Visual Basic)

await – – operátor (Referenční dokumentace jazyka C#)

FromResult``1

Koncepty

Řízení toku v asynchronních programech (C# a Visual Basic)