Start Multiple Async Tasks and Process Them As They Complete (Visual Basic) (Inicio de varias tareas asincrónicas y cómo procesarlas a medida que se completan [Visual Basic])
Si usa Task.WhenAny, puede iniciar varias tareas a la vez y procesarlas una por una a medida que se completen, en lugar de procesarlas en el orden en el que se han iniciado.
En el siguiente ejemplo se usa una consulta para crear una colección de tareas. Cada tarea descarga el contenido de un sitio web especificado. En cada iteración de un bucle while, una llamada awaited a WhenAny
devuelve la tarea en la colección de tareas que termine primero su descarga. Esa tarea se quita de la colección y se procesa. El bucle se repite hasta que la colección no contiene más tareas.
Nota
Para ejecutar los ejemplos, debe tener Visual Studio 2012 o posterior, y .NET Framework 4.5 o posterior, instalado en el equipo.
Descargar el ejemplo
Puede descargar el proyecto completo de Windows Presentation Foundation (WPF) desde Async Sample: Fine Tuning Your Application (Ejemplo de Async: Ajuste de la aplicación) y después seguir estos pasos.
Descomprima el archivo descargado y, a continuación, inicie Visual Studio.
En la barra de menús, elija Archivo, Abrir, Proyecto o solución.
En el cuadro de diálogo Abrir proyecto, abra la carpeta que contiene el código de ejemplo que descomprimió y después abra el archivo de la solución (.sln) para AsyncFineTuningVB.
En el Explorador de soluciones, abra el menú contextual del proyecto ProcessTasksAsTheyFinish y, después, pulse Establecer como proyecto de inicio.
Pulse la tecla F5 para ejecutar el proyecto.
Presione las teclas Ctrl+F5 para ejecutar el proyecto sin depurarlo.
Ejecute el proyecto varias veces para comprobar que las longitudes que se han descargado no aparecen siempre en el mismo orden.
Si no desea descargar el proyecto, puede revisar el archivo MainWindow.xaml.vb al final de este tema.
Compilación del ejemplo
Este ejemplo se agrega al código desarrollado en Cancelar las tareas asincrónicas restantes cuando se completa una (Visual Basic) y usa la misma interfaz de usuario.
Para generar el ejemplo personalmente, paso a paso, siga las instrucciones de la sección "Descargar el ejemplo", pero elija CancelAfterOneTask como el Proyecto de inicio. Agregue los cambios de este tema al método AccessTheWebAsync
de ese proyecto. Los cambios se marcan con asteriscos.
El proyecto CancelAfterOneTask ya incluye una consulta que, cuando se ejecuta, crea una colección de tareas. Cada llamada a ProcessURLAsync
en el siguiente código devuelve un objeto Task<TResult> donde TResult
es un entero.
Dim downloadTasksQuery As IEnumerable(Of Task(Of Integer)) =
From url In urlList Select ProcessURLAsync(url, client, ct)
En el archivo MainWindow.xaml.vb del proyecto, realice los siguientes cambios en el método AccessTheWebAsync
.
Ejecute la consulta aplicando Enumerable.ToList en lugar de ToArray.
Dim downloadTasks As List(Of Task(Of Integer)) = downloadTasksQuery.ToList()
Agregue un bucle while que realice los pasos siguientes para cada tarea de la colección.
Espera una llamada a
WhenAny
para identificar la primera tarea en la colección para finalizar su descarga.Dim finishedTask As Task(Of Integer) = Await Task.WhenAny(downloadTasks)
Quita la tarea de la colección.
downloadTasks.Remove(finishedTask)
Espera
finishedTask
, que se devuelve mediante una llamada aProcessURLAsync
. La variablefinishedTask
es un Task<TResult> dondeTReturn
es un entero. La tarea ya está completa, pero la espera para recuperar la longitud del sitio web descargado, como se muestra en el ejemplo siguiente.Dim length = Await finishedTask resultsTextBox.Text &= String.Format(vbCrLf & "Length of the downloaded website: {0}" & vbCrLf, length)
Debe ejecutar el proyecto varias veces para comprobar que las longitudes que se han descargado no aparecen siempre en el mismo orden.
Precaución
Puede usar WhenAny
en un bucle, como se describe en el ejemplo, para solucionar problemas que implican un número reducido de tareas. Sin embargo, otros enfoques son más eficaces si hay que procesar un gran número de tareas. Para obtener más información y ejemplos, vea Processing Tasks as they complete (Procesamiento de tareas a medida que se completan).
Ejemplo completo
El código siguiente es el texto completo del archivo MainWindow.xaml.vb para el ejemplo. Los asteriscos marcan los elementos que se agregaron para este ejemplo.
Observe que debe agregar una referencia para System.Net.Http.
Puede descargar el proyecto desde Async Sample: Ajuste de la aplicación.
' Add an Imports directive and a reference for System.Net.Http.
Imports System.Net.Http
' Add the following Imports directive for System.Threading.
Imports System.Threading
Class MainWindow
' Declare a System.Threading.CancellationTokenSource.
Dim cts As CancellationTokenSource
Private Async Sub startButton_Click(sender As Object, e As RoutedEventArgs)
' Instantiate the CancellationTokenSource.
cts = New CancellationTokenSource()
resultsTextBox.Clear()
Try
Await AccessTheWebAsync(cts.Token)
resultsTextBox.Text &= vbCrLf & "Downloads complete."
Catch ex As OperationCanceledException
resultsTextBox.Text &= vbCrLf & "Downloads canceled." & vbCrLf
Catch ex As Exception
resultsTextBox.Text &= vbCrLf & "Downloads failed." & vbCrLf
End Try
' Set the CancellationTokenSource to Nothing when the download is complete.
cts = Nothing
End Sub
' You can still include a Cancel button if you want to.
Private Sub cancelButton_Click(sender As Object, e As RoutedEventArgs)
If cts IsNot Nothing Then
cts.Cancel()
End If
End Sub
' Provide a parameter for the CancellationToken.
' Change the return type to Task because the method has no return statement.
Async Function AccessTheWebAsync(ct As CancellationToken) As Task
Dim client As HttpClient = New HttpClient()
' Call SetUpURLList to make a list of web addresses.
Dim urlList As List(Of String) = SetUpURLList()
' ***Create a query that, when executed, returns a collection of tasks.
Dim downloadTasksQuery As IEnumerable(Of Task(Of Integer)) =
From url In urlList Select ProcessURLAsync(url, client, ct)
' ***Use ToList to execute the query and start the download tasks.
Dim downloadTasks As List(Of Task(Of Integer)) = downloadTasksQuery.ToList()
' ***Add a loop to process the tasks one at a time until none remain.
While downloadTasks.Count > 0
' ***Identify the first task that completes.
Dim finishedTask As Task(Of Integer) = Await Task.WhenAny(downloadTasks)
' ***Remove the selected task from the list so that you don't
' process it more than once.
downloadTasks.Remove(finishedTask)
' ***Await the first completed task and display the results.
Dim length = Await finishedTask
resultsTextBox.Text &= String.Format(vbCrLf & "Length of the downloaded website: {0}" & vbCrLf, length)
End While
End Function
' Bundle the processing steps for a website into one async method.
Async Function ProcessURLAsync(url As String, client As HttpClient, ct As CancellationToken) As Task(Of Integer)
' GetAsync returns a Task(Of HttpResponseMessage).
Dim response As HttpResponseMessage = Await client.GetAsync(url, ct)
' Retrieve the website contents from the HttpResponseMessage.
Dim urlContents As Byte() = Await response.Content.ReadAsByteArrayAsync()
Return urlContents.Length
End Function
' Add a method that creates a list of web addresses.
Private Function SetUpURLList() As List(Of String)
Dim urls = New List(Of String) From
{
"https://msdn.microsoft.com",
"https://msdn.microsoft.com/library/hh290138.aspx",
"https://msdn.microsoft.com/library/hh290140.aspx",
"https://msdn.microsoft.com/library/dd470362.aspx",
"https://msdn.microsoft.com/library/aa578028.aspx",
"https://msdn.microsoft.com/library/ms404677.aspx",
"https://msdn.microsoft.com/library/ff730837.aspx"
}
Return urls
End Function
End Class
' Sample output:
' Length of the download: 226093
' Length of the download: 412588
' Length of the download: 175490
' Length of the download: 204890
' Length of the download: 158855
' Length of the download: 145790
' Length of the download: 44908
' Downloads complete.
Consulte también
- WhenAny
- Fine-Tuning Your Async Application (Visual Basic) (Ajuste de una aplicación asincrónica [Visual Basic])
- Programación asincrónica con Async y Await (Visual Basic)
- Ejemplo de async: Ajuste de la aplicación