Tipi restituiti asincroni (Visual Basic)
I metodi asincroni hanno tre possibili tipi restituiti: Task<TResult>, Task e void. In Visual Basic il tipo restituito void è scritto come routine Sub. Per altre informazioni sui metodi asincroni, vedere Programmazione asincrona con Async e Await (Visual Basic).
Ogni tipo restituito viene esaminato in una delle sezioni seguenti e alla fine dell'argomento è disponibile un esempio completo che usa tutti i tre tipi.
Nota
Per eseguire l'esempio, è necessario che nel computer siano installati Visual Studio 2012 o versioni successive e .NET Framework 4.5 o versioni successive.
Tipo restituito Task(T)
Il tipo restituito Task<TResult> viene usato per un metodo asincrono che contiene un'istruzione Return in cui il tipo dell'operando è TResult
.
Nell'esempio seguente il metodo asincrono TaskOfT_MethodAsync
contiene un'istruzione return che restituisce un valore intero. La dichiarazione del metodo deve quindi specificare un tipo restituito di Task(Of Integer)
.
' 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
Quando TaskOfT_MethodAsync
viene chiamato da un'espressione await, l'espressione recupera il valore intero (valore di leisureHours
) archiviato nell'attività restituita da TaskOfT_MethodAsync
. Per altre informazioni sulle espressioni await, vedere operatore await.
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()
È possibile capire meglio il modo in cui ciò avviene separando la chiamata a TaskOfT_MethodAsync
dall'applicazione di Await
, come illustrato dal codice seguente. Una chiamata al metodo TaskOfT_MethodAsync
che non viene immediatamente attesa restituisce un tipo Task(Of Integer)
, come ci si aspetterebbe dalla dichiarazione del metodo. Nell'esempio, l'attività viene assegnata alla variabile integerTask
. Poiché integerTask
è un Task<TResult>, contiene una proprietà Result di tipo TResult
. In questo caso, TResult rappresenta un tipo Integer. Quando si applica Await
a integerTask
, l'espressione await restituisce il contenuto della proprietà Result di integerTask
. Il valore viene assegnato alla variabile result2
.
Avviso
La proprietà Result è una proprietà di blocco. Se si prova ad accedervi prima del completamento dell'attività, il thread attualmente attivo viene bloccato fino a quando l'attività non viene completata e il valore non è disponibile. Nella maggior parte dei casi, è consigliabile accedere al valore usando Await
invece di accedere direttamente alla proprietà.
' 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 &= "Application can continue working while the Task(Of T) runs. . . . " & vbCrLf
Dim result2 As Integer = Await integerTask
Le istruzioni di visualizzazione nel codice seguente verificano che i valori della variabile result1
, della variabile result2
e della proprietà Result
siano identici. Si noti che la proprietà Result
è una proprietà di blocco e non ci si deve accedere prima che la sua attività sia stata completata.
' Display the values of the result1 variable, the result2 variable, and
' the resultTask.Result property.
textBox1.Text &= vbCrLf & $"Value of result1 variable: {result1}" & vbCrLf
textBox1.Text &= $"Value of result2 variable: {result2}" & vbCrLf
textBox1.Text &= $"Value of resultTask.Result: {integerTask.Result}" & vbCrLf
Tipo restituito Task
I metodi asincroni che non contengono un'istruzione return o che contengono un'istruzione return che non restituisce un operando hanno in genere il tipo restituito Task. Tali metodi sarebbero routine Sub se fossero state scritte per l'esecuzione sincrona. Se si usa un tipo restituito Task
per un metodo asincrono, un metodo chiamante può usare un operatore Await
per sospendere il completamento del chiamante fino a quando il metodo asincrono chiamato non abbia terminato l'operazione.
Nell'esempio seguente il metodo asincrono Task_MethodAsync
non contiene un'istruzione return. Di conseguenza, si specifica un tipo restituito Task
per il metodo, che consente a Task_MethodAsync
di essere atteso. La definizione del tipo Task
non include una proprietà Result
per archiviare 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 &= vbCrLf & "Sorry for the delay. . . ." & vbCrLf
' This method has no return statement, so its return type is Task.
End Function
Task_MethodAsync
viene chiamato e atteso usando un'istruzione await invece di un'espressione await, simile all'istruzione chiamante per un metodo sincrono Sub
o che restituisce void. L'applicazione di un operatore Await
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()
Come nell'esempio di Task<TResult> precedente, è possibile separare la chiamata a Task_MethodAsync
dall'applicazione di un operatore Await
, come illustrato dal codice seguente. Tuttavia, si noti che un tipo Task
non ha una proprietà Result
e che quando viene applicato un operatore await a un tipo Task
non viene prodotto alcun valore.
Il codice seguente separa la chiamata di Task_MethodAsync
dall'attesa dell'attività restituita da 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 &= vbCrLf & "Application can continue working while the Task runs. . . ." & vbCrLf
Await simpleTask
Tipo restituito Void
L'uso principale delle procedure Sub
è nei gestori degli eventi, in cui non esiste alcun tipo restituito (detto tipo restituito void in altri linguaggi). Un tipo restituito void può essere usato anche per eseguire l'override di metodi che restituiscono void o per metodi che eseguono attività che possono essere categorizzate come "Fire and Forget". È consigliabile tuttavia restituire un tipo Task
ogni volta che è possibile, perché un metodo asincrono che restituisce void non può essere atteso. Qualsiasi chiamante di questo metodo deve poter continuare fino al completamento senza attendere il completamento del metodo asincrono chiamato e il chiamante deve essere indipendente da qualsiasi eccezione o valore generato dal metodo asincrono.
Il chiamante di un metodo asincrono che restituisce void non può intercettare le eccezioni generate dal metodo ed è probabile che queste eccezioni non gestite provochino un errore dell'applicazione. Se si verifica un'eccezione in un metodo asincrono che restituisce Task o Task<TResult>, l'eccezione viene archiviata nell'attività restituita e rigenerata durante l'attesa dell'attività. Di conseguenza, verificare che qualsiasi metodo asincrono in grado di produrre un'eccezione abbia un tipo restituito Task o Task<TResult> e che sia impostata l'attesa per le chiamate al metodo.
Per altre informazioni su come intercettare eccezioni nei metodi asincroni, vedere Istruzione Try...Catch...Finally.
Il codice seguente definisce un gestore 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
Esempio completo
Il progetto Windows Presentation Foundation (WPF) seguente contiene gli esempi di codice di questo argomento.
Per eseguire il progetto, effettuare i passaggi seguenti:
Avviare Visual Studio.
Nella barra dei menu scegliere File, Nuovo, Progetto.
Verrà visualizzata la finestra di dialogo Nuovo progetto .
Nella categoria Installati, Modelli scegliere Visual Basic e quindi scegliere Windows. Dall'elenco dei tipi di progetto scegliere Applicazione WPF.
Immettere
AsyncReturnTypes
come nome del progetto e scegliere 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, aprire il menu di scelta rapida per MainWindow.xaml in Esplora soluzioni e quindi scegliere Apri.
Nella finestra XAML di MainWindow.xaml sostituire il codice con quello seguente.
<Window x:Class="MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://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>
Nella finestra di progettazionedi MainWindow.xaml verrà visualizzata una finestra contenente una casella di testo e un pulsante.
In Esplora soluzioni aprire il menu di scelta rapida per MainWindow.xaml.vb e quindi scegliere Visualizza codice.
Sostituire il codice in MainWindow.xaml.vb con quello riportato di seguito.
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 &= "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 &= vbCrLf & $"Value of result1 variable: {result1}" & vbCrLf textBox1.Text &= $"Value of result2 variable: {result2}" & vbCrLf textBox1.Text &= $"Value of resultTask.Result: {integerTask.Result}" & vbCrLf ' 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 &= 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 &= vbCrLf & "Sorry for the delay. . . ." & vbCrLf ' This method has no return statement, so its return type is Task. End Function End Class
Premere il tasto F5 per eseguire il programma e quindi scegliere il pulsante Start .
Dovrebbe venire visualizzato l'output seguente:
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.