Condividi tramite


Tipi restituiti asincroni (C# e Visual Basic)

I metodi asincroni hanno tre tipi restituibili possibili: Task, Taske void. In Visual Basic, il tipo restituito void viene scritto come routine In. Per ulteriori informazioni su metodi async, vedere Programmazione asincrona con Async e Await (C# e Visual Basic).

Ogni tipo restituito viene valutato in una delle seguenti sezioni ed è possibile trovare un esempio completo che utilizza tutti e tre i tipi alla fine dell'argomento.

Nota

Per eseguire l'esempio, è necessario che Visual Studio 2012, Visual Studio 2013, Visual Studio Express 2012 per Windows Desktop,Visual Studio Express 2013 per Windows o .NET Framework 4.5 o 4.5.1 siano installati sul computer.

Di seguito sono elencate le diverse sezioni di questo argomento.

  • Attività (T) tipo restituito
  • Attività tipo restituito
  • Tipo restituito void
  • Esempio completo
  • Argomenti correlati

Attività (T) tipo restituito

Il tipo restituito Task utilizzato per un metodo async contenente un'istruzione Return (Visual Basic) o return (C#) in cui l'operando è di tipo TResult.

Nell'esempio seguente, il metodo async TaskOfT_MethodAsync contiene un'istruzione return che restituisce un Integer. Pertanto, la dichiarazione del metodo deve specificare un tipo restituito Task(Of Integer) in Visual Basic o Task<int> in 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;
}

Quando TaskOfT_MethodAsync viene chiamato dall'interno di un'espressione di attesa, l'espressione di attesa recupera il valore integer (il valore leisureHours) archiviato nell'attività restituita da TaskOfT_MethodAsync. Per ulteriori informazioni sulle espressioni di attesa, vedere Opertore Await (Visual Basic) or await (Riferimenti per C#).

Il codice seguente chiama e attende il metodo TaskOfT_MethodAsync. Il risultato viene assegnato alla variabile 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();

È possibile comprendere come si verifica questa separazione della chiamata a TaskOfT_MethodAsync dall'applicazione Await o dall' await, come illustrato nel codice. Una chiamata al metodo TaskOfT_MethodAsync non restituisce immediatamente l'attesa di un Task(Of Integer) o Task<int>, come previsto dalla dichiarazione del metodo. L'attività viene assegnata alla variabile integerTask nell'esempio. Poiché integerTask è Task, contiene una proprietà Result di tipo TResult. In questo caso, TResult rappresenta un tipo Integer. Quando Await o await viene applicato a integerTask, l'espressione di attesa restituisce il contenuto della proprietà Result integerTask. Il valore viene assegnato alla variabile result2.

Avviso

La proprietà Result è una proprietà del blocco.Se si tenta di accedervi prima che la relativa attività venga completata, il thread attualmente attivo viene bloccato finché l'attività non viene completata e il valore sia disponibile.Nella maggior parte dei casi, è necessario accedere al valore utilizzando Await o await anziché accedere alla proprietà direttamente.

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

Le istruzioni visualizzate nel codice seguente servono per verificare che i valori della variabile result1, la variabile result2 e la proprietà Result siano identici. Tenere presente che la proprietà Result è una proprietà di blocco e non deve essere eseguito prima che la relativa attività sia stata attesa.

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

Attività tipo restituito

I metodi asincroni che non contengono un'istruzione return o contenenti un'istruzione return che non restituisce un operando solitamente restituiscono un tipo di Task. Tali metodi restituirebbero void (procedure diIn in Visual Basic) se sono scritti per funzionare in modo sincrono. Se si utilizza un tipo restituito Task per un metodo async, un metodo chiamante può utilizzare un operatore di attesa per sospendere il completamento del chiamante finché il metodo chiamato async non è stato completato.

Nell'esempio seguente, il metodo Task_MethodAsync async non contiene un'istruzione return. Pertanto, è possibile specificare un tipo restituito Task per il metodo, che consente Task_MethodAsync in attesa. La definizione del tipo Task non include una proprietà Result per memorizzare un valore restituito.

' 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 viene chiamato utilizzando un'istruzione await anziché un'espressione di attesa, simile all'istruzione chiamante per Sub sincrono o il metodo ritorna void. L'applicazione di un operatore di attesa in questo caso non produce un valore.

Il codice seguente chiama e attende il metodo 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();

Come nell'esempio precedente Task, è possibile separare la chiamata a Task_MethodAsync dall'applicazione di un operatore di attesa, come illustrato nel codice seguente. Tuttavia, ricordare che Task non dispone di una proprietà Result e che nessun valore viene generato quando un operatore di attesa viene applicato a Task.

Il codice seguente separa la chiamata Task_MethodAsync dalle attività in attesa che Task_MethodAsync restituisce.

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

Tipo restituito void

L'utilizzo primario del tipo restituito void (Sub le procedure in Visual Basic) in gestori eventi, in cui è richiesto di ritorno un tipo void. Il valore restituito void può anche essere utilizzato per eseguire l'override su metodi che restituiscono void o per i metodi che eseguono le attività che possono essere suddivise in categorie come "autonome dopo il lancio". Tuttavia, è necessario restituire Task se possibile, un metodo void che restituisce async non può essere in attesa. Qualsiasi chiamante di tale metodo deve poter essere in grado di continuare fino a completamento senza attendere la fine del metodo asincrono chiamato, e il chiamante deve essere indipendente da ogni valore o eccezione generata dal metodo asincrono.

Il chiamante di un metodo void che ritorna async non può intercettare le eccezioni generate dal metodo e tali eccezioni non gestite è probabile che faccino fallire l'applicazione. Se si verifica un'eccezione in un metodo asincrono che restituisce Task o Task, l'eccezione viene archiviata nell'attività restituita e generata quando l'attività è in attesa. Di conseguenza, bisogna assicurarsi che qualsiasi metodo async possa generare un'eccezione sia un tipo restituito Task o Task e che le chiamate al metodo vengano attese.

Per ulteriori informazioni su come intercettare eccezioni nei metodi asincroni, vedere try-catch (Riferimenti per C#) o Istruzione Try...Catch...Finally (Visual Basic).

Il codice seguente definisce un gestore di eventi asincroni.

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

Esempio completo

Il seguente progetto Windows Presentation Foundation (WPF) contiene l'esempi di codice da questo argomento.

Per eseguire il progetto, attenersi alla procedura descritta di seguito:

  1. Avviare Visual Studio.

  2. Nella barra dei menu, scegliere File, Nuovo, Progetto.

    Verrà visualizzata la finestra di dialogo Nuovo progetto.

  3. Nella categoria Installato, Modelli scegliere Visual Basic o Visual C#, quindi Windows. Scegliere Applicazione (WPF) dall'elenco dei tipi di progetto.

  4. Immettere AsyncReturnTypes come nome del progetto e quindi scegliere il pulsante OK.

    Il nuovo progetto verrà visualizzato in Esplora soluzioni.

  5. Nell'editor di codice di Visual Studio, scegliere la scheda MainWindow.xaml.

    Se la scheda non è visibile, scegliere dal menu di scelta rapida per MainWindow.xaml in Esplora soluzioni quindi scegliere Apri.

  6. Nella finestra XAML di MainWindow.xaml, sostituire il codice con il seguente.

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

    Una semplice finestra che contiene una casella di testo e un pulsante vengono visualizzati nella finestra Progettazione di MainWindow.xaml.

  7. In Esplora soluzioni, aprire il menu di scelta rapida per MainWindow.xaml.vb o MainWindow.xaml.cs e scegliere Visualizza Codice.

  8. Sostituire il codice in MainWindow.xaml.vb o MainWindow.xaml.cs con il codice seguente.

    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. Premere il tasto F5 per eseguire il programma, quindi scegliere il pulsante Avvia.

    Dovrebbe comparire il seguente output.

    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.
    

Vedere anche

Attività

Procedura dettagliata: accesso al Web tramite Async e Await (C# e Visual Basic)

Procedura dettagliata: utilizzo del debugger con metodi Async

Riferimenti

async (Riferimenti per C#)

Async (Visual Basic)

Opertore Await (Visual Basic)

await (Riferimenti per C#)

FromResult``1

Concetti

Flusso di controllo in programmi asincroni (C# e Visual Basic)