Tipi restituiti asincroni (C# e Visual Basic)
i metodi di Async hanno tre tipi restituibili possibili: Task<TResult>, 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 express 2012 per Windows Desktop, o .NET Framework 4,5 installato nel 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<TResult> 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 intero (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<TResult>, contiene una proprietà Result di tipo TResult.In questo caso, TResult rappresenta un tipo intero.Quando Await o await viene applicato a integerTask, l'espressione di attesa restituisce il contenuto della proprietà ResultintegerTask.Il valore viene assegnato alla variabile result2.
Attenzione |
---|
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 è restituito un tipo 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<TResult>, è possibile separare la chiamata Task_MethodAsync dall'applicazione di un operatore di attesa, come illustrato nel codice.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 chiamata di tale metodo deve poter completare senza attendere il metodo chiamato async e il chiamante deve essere indipendente da qualsiasi valore o eccezione che il metodo async genera.
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<TResult>, 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<TResult> e che le chiamate al metodo vengano attese.
Per ulteriori informazioni su come intercettare eccezioni nei metodi async, 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:
Avviare Visual Studio.
Nella barra del menu, scegliere File, Nuovo, Progetto.
Verrà visualizzata la finestra di dialogo Nuovo progetto.
In Installato, la categoria Modelli, scegliere Visual Basic o Visual C#quinFinestre.Scegliere Applicazione WPF dall'elenco di tipi di progetto.
Immettere AsyncReturnTypes come nome del progetto e quindi scegliere il pulsante OK.
Il nuovo progetto verrà visualizzato in Esplora soluzioni.
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 soluzionie quindi scegliere Apri.
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.
In Esplora soluzioni, aprire il menu di scelta rapida per MainWindow.xaml.vb o MainWindow.xaml.cs e scegliere Visualizza Codice.
Sostituire il codice in MainWindow.xaml.vb o MainWindow.xaml.cs con il 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. } } }
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
Concetti
Flusso di controllo in programmi asincroni (C# e Visual Basic)