Async Return Types (Visual Basic) (Tipos de valor devuelto de Async [Visual Basic])
Los métodos asincrónicos tienen tres posibles tipos devueltos: Task<TResult>, Task y void. En Visual Basic, el tipo de valor devuelto void se escribe como un procedimiento Sub. Para obtener más información sobre los métodos asincrónicos, vea Programación asincrónica con Async y Await (Visual Basic).
Cada tipo de valor devuelto se examina en una de las siguientes secciones, y puede encontrar un ejemplo completo que usa los tres tipos al final del tema.
Nota
Para ejecutar el ejemplo, debe tener instalado en el equipo Visual Studio 2012 o posterior y .NET Framework 4.5 o posterior.
Tipo de valor devuelto Task(T)
El tipo de valor devuelto Task<TResult> se usa para un método asincrónico que contiene una instrucción Return en la que el operando tiene el tipo TResult
.
En el ejemplo siguiente, el método asincrónico TaskOfT_MethodAsync
contiene una instrucción return que devuelve un entero. Por tanto, la declaración del método debe tener un tipo de valor devuelto de 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
Cuando se llama a TaskOfT_MethodAsync
desde una expresión await, esta recupera el valor entero (el valor de leisureHours
) que está almacenado en la tarea que TaskOfT_MethodAsync
devuelve. Para más información sobre las expresiones await, vea Operador Await.
El código siguiente llama y espera al método TaskOfT_MethodAsync
. El resultado se asigna a la variable result1
.
' Call and await the Task(Of T)-returning async method in the same statement.
Dim result1 As Integer = Await TaskOfT_MethodAsync()
Comprenderá mejor cómo sucede esto separando la llamada a TaskOfT_MethodAsync
de la aplicación de Await
, como se muestra en el código siguiente. Una llamada al método TaskOfT_MethodAsync
que no se espera inmediatamente devuelve Task(Of Integer)
, como se podría esperar de la declaración del método. La tarea se asigna a la variable integerTask
en el ejemplo. Dado que integerTask
es Task<TResult>, contiene una propiedad Result de tipo TResult
. En este caso, TResult representa un tipo entero. Cuando Await
se aplica a integerTask
, la expresión await se evalúa en el contenido de la propiedad Result de integerTask
. El valor se asigna a la variable result2
.
Advertencia
La propiedad Result es una propiedad de bloqueo. Si se intenta acceder a ella antes de que termine su tarea, se bloquea el subproceso que está activo actualmente hasta que finaliza la tarea y el valor está disponible. En la mayoría de los casos, se debe tener acceso al valor usando Await
en lugar de tener acceso directamente a la propiedad.
' 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
Las instrucciones mostradas en el siguiente código comprueban que los valores de la variable result1
, la variable result2
y la propiedad Result
son los mismos. Recuerde que la propiedad Result
es una propiedad bloqueo y no se debe tener acceso a ella antes de haber esperado a su tarea.
' 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 de valor devuelto Task
Los métodos asincrónicos que no contienen una instrucción return o que contienen una instrucción return que no devuelve un operando tienen normalmente un tipo de valor devuelto de Task. Estos métodos deben ser procedimientos Sub si se escribieron para ejecutarse de forma sincrónica. Si se usa un tipo de valor devuelto Task
para un método asincrónico, un método de llamada puede usar un operador Await
para suspender la finalización del llamador hasta que finalice el método asincrónico llamado.
En el ejemplo siguiente, el método asincrónico Task_MethodAsync
no contiene una instrucción return. Por tanto, se especifica un tipo de valor devuelto de Task
para el método, lo que permite aplicar await a Task_MethodAsync
. La definición del tipo Task
no incluye una propiedad Result
para almacenar un valor devuelto.
' 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
Se llama y se espera a Task_MethodAsync
mediante una instrucción await en lugar de una expresión await, similar a la instrucción de llamada para un Sub
sincrónica o método que devuelve void. En este caso, la aplicación de un operador Await
no genera un valor.
El código siguiente llama y espera al método Task_MethodAsync
.
' Call and await the Task-returning async method in the same statement.
Await Task_MethodAsync()
Igual que en el ejemplo Task<TResult> anterior, puede separar la llamada a Task_MethodAsync
desde la aplicación de un operador Await
, como muestra el código siguiente. Pero recuerde que una Task
no tiene una propiedad Result
y que no se genera ningún valor cuando se aplica un operador await a una Task
.
El código siguiente separa la llamada de Task_MethodAsync
de la espera de la tarea que Task_MethodAsync
devuelve.
' 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 de valor devuelto Void
El uso principal de los procedimientos Sub
es en los controladores de eventos, donde no hay ningún tipo de valor devuelto (denominado tipo de valor devuelto void en otros lenguajes). También se puede usar una devolución void para invalidar los métodos que devuelven void o para los métodos que realizan actividades que se pueden clasificar como "fire and forget" (dispare y olvídese). Sin embargo, debe devolver Task
siempre que sea posible, ya que no se puede esperar a un método asincrónico que devuelve void. Cualquier llamador de este método debe poder continuar hasta completarse sin esperar a que finalice el método asincrónico llamado y el llamador debe ser independiente de los valores o las excepciones que genera el método asincrónico.
El llamador de un método asincrónico que devuelve void no puede capturar las excepciones emitidas desde el método y dichas excepciones no controladas pueden provocar un error de la aplicación. Si se produce una excepción en un método asincrónico que devuelve Task o Task<TResult>, la excepción se almacena en la tarea devuelta y se vuelve a emitir cuando se espera la tarea. Por tanto, asegúrese de que cualquier método asincrónico que puede producir una excepción tiene un tipo de valor devuelto de Task o Task<TResult> y que se esperan llamadas al método.
Para más información sobre cómo capturar excepciones en métodos asincrónicos, vea Instrucción Try...Catch...Finally.
El código siguiente define un controlador de eventos asincrónico.
' 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
Ejemplo completo
El siguiente proyecto de Windows Presentation Foundation (WPF) contiene los ejemplos de código de este tema.
Para ejecutar el proyecto, realice los pasos siguientes:
Inicie Visual Studio.
En la barra de menús, elija Archivo, Nuevo, Proyecto.
Aparece el cuadro de diálogo Nuevo proyecto .
En la categoría Instalado, Plantillas, seleccione Visual Basic y luego Windows. Seleccione Aplicación WPF en la lista de tipos de proyecto.
Escriba
AsyncReturnTypes
como el nombre del proyecto y elija el botón Aceptar.El proyecto nuevo aparece en el Explorador de soluciones.
En el Editor de código de Visual Studio, elija la pestaña MainWindow.xaml .
Si la pestaña no es visible, abra el menú contextual de MainWindow.xaml en el Explorador de soluciones y después haga clic en Abrir.
En la ventana XAML de MainWindow.xaml, reemplace el código por el código siguiente.
<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>
En la ventana Diseño de MainWindow.xaml aparece una ventana simple que contiene un cuadro de texto y un botón.
En el Explorador de soluciones, abra el menú contextual de MainWindow.xaml.vb y seleccione Ver código.
Reemplace el código en el archivo MainWindow.xaml.vb por el código siguiente.
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
Presione la tecla F5 para ejecutar el programa y elija el botón Inicio .
Deben aparecer los siguientes resultados:
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.
Consulte también
- FromResult
- Tutorial: Acceso a web usando Async y Await (C# y Visual Basic)
- Control Flow in Async Programs (Visual Basic) (Flujo de control en programas asincrónicos [Visual Basic])
- Async
- Await (operador)
Comentarios
https://aka.ms/ContentUserFeedback.
Próximamente: A lo largo de 2024 iremos eliminando gradualmente GitHub Issues como mecanismo de comentarios sobre el contenido y lo sustituiremos por un nuevo sistema de comentarios. Para más información, vea:Enviar y ver comentarios de