Partager via


Types de retour Async (C# et Visual Basic)

Les méthodes async ont trois types de retour possibles : Task, Task et void. Dans Visual Basic, le type de renvoi d'annulation est écrit comme procédure Sub. Pour plus d'informations sur les méthodes async, consultez Programmation asynchrone avec Async et Await (C# et Visual Basic).

Chaque type de retour est examiné dans l'une des sections suivantes, et vous pouvez obtenir un exemple complet qui utilise les trois types à la fin de cette rubrique.

Notes

Pour exécuter l'exemple, Visual Studio 2012, Visual Studio 2013, Visual Studio Express 2012 pour Windows Desktop, Visual Studio Express 2013 pour Windows ou le .NET Framework 4.5 ou 4.5.1 doit être installé sur votre ordinateur.

Cette rubrique comprend les sections suivantes.

  • Type de retour Task(T)
  • Type de retour Task
  • Type de retour void
  • Exemple complet
  • Rubriques connexes

Type de retour Task(T)

Le type de retour Task est utilisé pour une méthode async qui contient une instruction Return (Visual Basic) or return (C#) dans laquelle l'opérande a le type TResult.

Dans l'exemple suivant, la méthode async TaskOfT_MethodAsync contient une instruction return qui retourne un entier. Par conséquent, la déclaration de méthode doit spécifier un type de retour Task(Of Integer) dans Visual Basic ou Task<int> en 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;
}

Lorsque TaskOfT_MethodAsync est appelé depuis une expression await, l'expression await récupère la valeur entière (la valeur leisureHours) qui est stockée dans la tâche retournée par TaskOfT_MethodAsync. Pour plus d'informations sur les expressions await, consultez Await, opérateur (Visual Basic) ou await (Référence C#).

Le code suivant appelle et attend la méthode TaskOfT_MethodAsync. La valeur est assignée à la variable 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();

Vous pouvez mieux comprendre comment cela arrive en séparant l'appel à TaskOfT_MethodAsync de l'application de Await ou de await, comme l'illustre le code suivant. Un appel à la méthode TaskOfT_MethodAsync qui n'est pas immédiatement attendu retourne une Task(Of Integer) ou une Task<int>, comme vous pourriez l'attendre de la déclaration de la méthode. La tâche est assignée à la variable integerTask dans l'exemple. Comme integerTask est un objet Task, il contient une propriété Result de type TResult. Dans ce cas, TResult représente un type d'entier. Lorsque Await ou await est appliqué à integerTask, l'expression await prend le contenu de la propriété Result de integerTask. La valeur est assignée à la variable result2.

Avertissement

La propriété Result est une propriété bloquante.Si vous tentez d'y accéder avant que sa tâche ne soit terminée, le thread qui est actuellement actif est bloqué jusqu'à ce que la tâche se termine et que la valeur soit disponible.Dans la plupart des cas, vous devez accéder à la valeur avec Await ou await au lieu d'accéder à la propriété directement.

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

Les instructions d'affichage dans le code suivant vérifient que les valeurs de la variable result1, de la variable result2 et de la propriété Result sont identiques. Souvenez -vous que la propriété Result est une propriété de blocage et qu'elle ne doit pas être accédée avant que sa tâche soit attendue.

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

Type de retour Task

Les méthodes async qui ne contiennent pas d'instruction return ou comportent une instruction return qui ne retourne pas d'opérande ont généralement un type de retour Task. Ces méthodes seraient des fonctions retournant une valeur void (procédures Sub en Visual Basic) si elles étaient écrites pour fonctionner de façon synchrone. Si vous utilisez un type de retour Task pour une méthode async, une méthode d'appel peut utiliser un opérateur d'attente pour interrompre l'achèvement de l'appelant jusqu'à ce que la méthode async appelée soit terminée.

Dans l'exemple suivant, la méthode async Task_MethodAsync ne contient pas d'instruction return. Par conséquent, vous spécifiez un type de retour Task pour la méthode, qui permet à Task_MethodAsync d'être attendu. La définition du type Task n'inclut pas une propriété Result pour stocker une valeur de retour.

' 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 est appelée et attendue à l'aide d'une instruction d'attente au lieu d'une expression d'attente, semblable à l'instruction d'appel pour une méthode synchrone Sub ou une méthode retournant une valeur void. L'application d'un opérateur await dans ce cas ne produit pas une valeur.

Le code suivant appelle et attend la méthode 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();

Comme dans l'exemple Taskprécédent, vous pouvez séparer l'appel à Task_MethodAsync de la demande d'un opérateur await, comme l'illustre le code suivant. Toutefois, n'oubliez pas que Task n'a pas de propriété Result, et qu'aucune valeur n'est produite lorsqu'un opérateur await est appliqué à Task.

Le code suivant sépare l'appel à Task_MethodAsync de l'attente de la tâche que Task_MethodAsync retourne.

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

Type de retour void

L'utilisation principale du type de retour void (procéduresSub en Visual Basic) est dans les gestionnaires d'événements, où un type de retour void est requis. Un retour void peut aussi être utilisé pour remplacer les méthodes void ou pour les méthodes qui exécutent les activités qui peuvent être catégorisées comme « autonomes après l'activation ». Toutefois, vous devez retourner Task dans la mesure du possible, car une méthode void async ne peut pas être attendue. Tout appelant de cette méthode doit pouvoir continuer jusqu'a l'achèvement sans attendre que la méthode async soit terminée, et l'appelant doit être indépendant de toutes les valeurs ou exceptions que la méthode async génère.

L'appelant d'une méthode asynchrone retournant une valeur void ne peut pas intercepter les exceptions levées depuis la méthode, et de telles exceptions non gérées peuvent causer l'échec de votre application. Si une exception se produit dans une méthode async qui retourne Task ou Task, l'exception est stockée dans la tâche retournée, et est à nouveau levée lorsque la tâche est attendue. Par conséquent, veillez à ce que n'importe quelle méthode async qui peut générer une exception ait un type de retour Task ou Task et que les appels à la méthode soient attendus.

Pour plus d'informations sur l'interception des exceptions dans les méthodes async, consultez try-catch (référence C#) ou Try...Catch...Finally, instruction (Visual Basic).

Le code suivant définit un gestionnaire d'événements asynchrones.

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

Exemple complet

Le projet Windows Presentation Foundation (WPF) suivant contient les exemples de code de cette rubrique.

Pour exécuter le projet, exécutez les étapes suivantes :

  1. Démarrez Visual Studio.

  2. Dans la barre de menus, sélectionnez Fichier, Nouveau, Projet.

    La boîte de dialogue Nouveau projet s'affiche.

  3. Dans la catégorie Installés, Modèles, choisissez Visual Basic ou Visual C#, puis Windows Store. Dans la liste des types de projet, choisissez Application WPF.

  4. Entrez AsyncReturnTypes comme nom du projet, puis cliquez sur OK.

    Le nouveau projet s'affiche dans l'Explorateur de solutions.

  5. Dans l'éditeur de code Visual Studio, choisissez l'onglet MainWindow.xaml.

    Si l'onglet n'est pas visible, ouvrez le menu contextuel de MainWindow.xaml dans Explorateur de solutions, puis choisissez Ouvrir.

  6. Dans la fenêtre XAML de MainWindow.xaml, remplacez le code par le code suivant.

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

    Une fenêtre simple qui contient une zone de texte et un bouton apparaît dans la fenêtre Design de MainWindow.xaml.

  7. Dans l'Explorateur de solutions, ouvrez le menu contextuel de MainWindow.xaml.vb ou MainWindow.xaml.cs, puis choisissez Afficher le Code.

  8. Remplacez le code dans MainWindow.xaml.vb ou MainWindow.xaml.cs par le code suivant.

    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. Choisissez la touche F5 pour exécuter le programme, puis choisissez le bouton Démarrer.

    La sortie suivante doit apparaître.

    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.
    

Voir aussi

Tâches

Procédure pas à pas : accès au Web avec Async et Await (C# et Visual Basic)

Procédure pas à pas : utilisation du débogueur avec les méthodes Async

Référence

async (référence C#)

Async (Visual Basic)

Await, opérateur (Visual Basic)

await (Référence C#)

FromResult``1

Concepts

Flux de contrôle dans les programmes Async (C# et Visual Basic)