Nota
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
Los métodos asincrónicos tienen tres tipos de valor devuelto posibles: Task<TResult>, Tasky 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 secciones siguientes y puede encontrar un ejemplo completo que use los tres tipos al final del tema.
Nota:
Para ejecutar el ejemplo, debe tener Visual Studio 2012 o versiones posteriores y .NET Framework 4.5 o posterior instalado en el equipo.
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 TaskOfT_MethodAsync
método asincrónico contiene una instrucción return que devuelve un entero. Por lo tanto, la declaración de método debe especificar 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 obtener más información sobre las expresiones await, vea Await Operator.
El siguiente código llama al método TaskOfT_MethodAsync
y lo espera. El resultado se asigna a la result1
variable .
' Call and await the Task(Of T)-returning async method in the same statement.
Dim result1 As Integer = Await TaskOfT_MethodAsync()
Puede 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 un 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 intenta acceder a ella antes de que finalice su tarea, el subproceso que está activo actualmente se bloquea hasta que se complete 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 display del código siguiente comprueban que los valores de la result1
variable, la result2
variable y la Result
propiedad 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 normalmente tienen un tipo de valor devuelto de Task. Estos métodos serían procedimientos Sub si se escribieran para ejecutarse sincrónicamente. 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 Task_MethodAsync
asincrónico no contiene una instrucción return. Por lo tanto, se especifica un tipo de retorno Task
para el método, lo que permite que Task_MethodAsync
sea esperado. La definición del Task
tipo no incluye una Result
propiedad 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 método Sub
sincrónico o que devuelve nulo. La aplicación de un Await
operador en este caso no genera un valor.
El siguiente código llama al método Task_MethodAsync
y lo espera.
' Call and await the Task-returning async method in the same statement.
Await Task_MethodAsync()
Como en el ejemplo anterior Task<TResult>, puede separar la llamada a Task_MethodAsync
de la aplicación de un operador Await
, como muestra el código siguiente. Sin embargo, recuerde que un Task
no tiene una propiedad Result
y que no se genera ningún valor cuando se aplica un operador await a un 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 dicho método debe poder continuar hasta completar sin esperar a que finalice el método asincrónico llamado, y el llamador debe ser independiente de los valores o excepciones que genere el método asincrónico.
El llamador de un método asincrónico que devuelve void no puede detectar excepciones arrojadas desde el método, y es probable que estas excepciones no controladas provoquen un error en su aplicación. Si se produce una excepción en un método asincrónico que devuelve un Task o un Task<TResult>, la excepción se almacena en la tarea devuelta y se lanza de nuevo cuando se aguarda 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 obtener más información sobre cómo detectar excepciones en métodos asincrónicos, vea Try... Catch... Finally Statement.
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.
Se abre el cuadro de diálogo Nuevo proyecto .
En la categoría Instalado, Plantillas , elija Visual Basic y, a continuación, elija Windows. Elija Aplicación WPF en la lista de tipos de proyecto.
Escriba
AsyncReturnTypes
como nombre del proyecto y, a continuación, 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 está visible, abra el menú contextual de MainWindow.xaml en el Explorador de soluciones y, a continuación, elija 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>
Una ventana simple que contiene un cuadro de texto y un botón aparece en la ventana Diseño de MainWindow.xaml.
En el Explorador de soluciones, abra el menú contextual de MainWindow.xaml.vb y seleccione Ver código.
Reemplace el código de 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 .
Debería aparecer la siguiente salida:
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.